カスタムドロップダウンテーブルの実装アプローチ
前回のリスト形式に続き、今回はQComboBoxのドロップダウン領域にテーブルビューを表示する高度なカスタマイズ手法を解説します。この実装では、鉄道サイトの地域選択インターフェースのような多列データ表現が可能となります。
主要コンポーネント設計
システムは以下のクラス構造で構築されています:
- BaseComboBox: 基本機能を提供する抽象基底クラス
- ListDropDown: 単一リスト表示の実装
- TableDropDown: テーブル表示の実装
- CustomHeaderView: カスタム描画するヘッダビュー
- CitySelector: 都市選択専用の実装クラス
基本インターフェース定義
class BaseComboBox : public QWidget {
public:
explicit BaseComboBox(ItemDisplayType type, QWidget* parent = nullptr);
void SetDelimiter(char delimiter);
void AddEntry(const QString& entry);
void AddEntries(const QVector<QString>& entries);
void SetEntryWidth(int width);
void SetEntryHeight(int height);
void SetMaxVisibleItems(int count);
protected:
virtual bool eventFilter(QObject*, QEvent*) override;
virtual void AppendEntry(const QString& entry) = 0;
virtual void AdjustEntryWidth(int width) = 0;
virtual void AdjustEntryHeight(int height) = 0;
QWidget* CreateEntryWidget(const QString& text);
private:
void InitializeComponents();
};
テーブルドロップダウンの実装
class TableDropDown : public BaseComboBox {
Q_OBJECT
public:
explicit TableDropDown(ItemDisplayType type = CheckableItem,
QWidget* parent = nullptr);
void SetColumnCount(int columns);
void SetHeaderLabels(const QStringList& labels);
void SetHeaderVisible(bool visible);
void FinalizeData();
protected:
virtual bool eventFilter(QObject*, QEvent*) override;
virtual void AppendEntry(const QString& entry) override;
virtual void AdjustEntryWidth(int width) override;
virtual void AdjustEntryHeight(int height) override;
virtual void PadIncompleteRows();
private slots:
void HandleHeaderClick(int index);
private:
void SetupTableView();
int m_ColumnCount = 2;
};
透過背景の実現手法
ドロップダウンの背景を透過させるには、親ウィジェットの属性設定が必要です:
if (QWidget* parent = comboBox->view()->parentWidget()) {
parent->setAttribute(Qt::WA_TranslucentBackground);
parent->setWindowFlags(Qt::Popup | Qt::FramelessWindowHint);
}
都市選択コンポーネントの使用例
CitySelector selector(parentWidget);
selector.SetDisplayType(LabelItem);
selector.SetHorizontalHeaders({"ABCDEF", "GHIJ", "KLMN", "PQRSTUVM", "XYZ"});
selector.SetVerticalHeaders({"A", "B", "C", "D", "E"});
selector.SetCurrentGroup('B');
selector.AddEntry("Beijing");
selector.AddEntry("Shanghai");
selector.FinalizeData();
スクロール位置のリセット処理
テーブルスクロール後の表示不具合を防ぐため、ドロップダウン非表示時にトップ位置にリセットします:
bool TableDropDown::eventFilter(QObject* target, QEvent* event) {
if (target == m_ComboBox->view()->parentWidget() &&
event->type() == QEvent::Hide) {
if (QTableWidget* table = qobject_cast(m_DropDownWidget)) {
table->scrollToTop();
}
}
return BaseComboBox::eventFilter(target, event);
}