Dalam praktiknya, terkadang perlu untuk menampilkan struktur data seperti pohon di QComboBox.
Komponen standar dalam Qt untuk struktur data seperti itu adalah QTreeView, apalagi,
QComboBox dapat menampilkan komponen ini di dalam dirinya sendiri, tetapi seperti biasa, ada ruang kecil dalam dokumentasi, karena Anda tidak hanya perlu menampilkan pohon, tetapi juga mengatur elemen saat ini yang dipilih oleh pengguna.
Mari kita lihat bagaimana melakukannya dengan benar.
Pertama, buat komponen itu sendiri, yang akan menampilkan data, untuk ini kita mewarisi dari QComboBox dan memberikannya properti yang kita butuhkan.
Di bagian tertutup kelas, kami mendeklarasikan variabel m_view kelas QTreeView, yang akan menampilkan pohon di QComboBox, mendefinisikan kembali 2 fungsi yang bertanggung jawab atas perilaku komponen ketika membuka dan menutup:
- membatalkan showPopup () override; - dieksekusi ketika pengguna memperluas daftar
- membatalkan hidePopup () menimpa; - dilakukan ketika pengguna memilih item dengan mengkliknya
Kami juga menambahkan fungsi hideColumn (int n), yang akan menyembunyikan kolom yang Anda butuhkan di QTreeView, karena jika model Anda terdiri dari beberapa kolom, QComboBox akan menunjukkan semuanya (komponen standar menggunakan daftar), yang akan terlihat sangat jelek
treecombobox.h
#ifndef TREECOMBOBOX_H #define TREECOMBOBOX_H #include <QtWidgets/QComboBox> #include <QtWidgets/QTreeView> class TreeComboBox final : public QComboBox { public: TreeComboBox(); void showPopup() override; void hidePopup() override; void hideColumn(int n); void expandAll(); void selectIndex(const QModelIndex &index); private: QTreeView *m_view = nullptr; }; #endif //TREECOMBOBOX_H
treecombobox.cpp
TreeComboBox::TreeComboBox() { m_view = new QTreeView; m_view->setFrameShape(QFrame::NoFrame); m_view->setEditTriggers(QTreeView::NoEditTriggers); m_view->setAlternatingRowColors(true); m_view->setSelectionBehavior(QTreeView::SelectRows); m_view->setRootIsDecorated(false); m_view->setWordWrap(true); m_view->setAllColumnsShowFocus(true); m_view->setItemsExpandable(false); setView(m_view); m_view->header()->setVisible(false); } void TreeComboBox::hideColumn(int n) { m_view->hideColumn(n); } void TreeComboBox::expandAll() { m_view->expandAll(); } void TreeComboBox::selectIndex(const QModelIndex &index) { setRootModelIndex(index.parent()); setCurrentIndex(index.row()); m_view->setCurrentIndex( index ); } void TreeComboBox::showPopup() { setRootModelIndex(QModelIndex()); QComboBox::showPopup(); } void TreeComboBox::hidePopup() { setRootModelIndex(m_view->currentIndex().parent()); setCurrentIndex( m_view->currentIndex().row()); QComboBox::hidePopup(); }
Di konstruktor, kita mengatur pohon yang perlu kita lihat sehingga terlihat "tertanam" di QComboBox, menghapus header, menyembunyikan elemen ekspansi dan mengaturnya sebagai elemen tampilan.
Trik untuk memasang item yang dipilih pengguna dengan benar di QComboBox adalah fungsi showPopup () dan hidePopup ().
Karena QComboBox bekerja dengan tampilan model "flat", itu tidak dapat mengatur indeks yang benar dari elemen yang dipilih pengguna dalam model pohon, karena mereka menggunakan indeks relatif terhadap elemen induk untuk ini:
showPopup ()
elemen root - kami mengatur indeks root ke indeks model yang tidak valid sehingga QComboBox menampilkan semua elemen model.
hidePopup ()
elemen root - kami mengatur indeks induk dari elemen model yang dipilih oleh pengguna, dan kemudian relatif terhadap elemen induk, kami mengatur elemen pengguna yang dipilih berdasarkan indeks.
Ini digunakan semua seperti ini:
int main(int argc, char *argv[]) { QApplication a(argc, argv); QWidget w; QStandardItemModel model; QStandardItem *parentItem = model.invisibleRootItem(); for (int i = 0; i < 4; ++i) { QStandardItem *item = new QStandardItem(QString("item %0").arg(i)); parentItem->appendRow(item); parentItem = item; } TreeComboBox t; t.setModel(&model); t.expandAll(); auto lay = new QVBoxLayout; lay->addWidget( &t); w.setLayout(lay); w.show(); return a.exec(); }
