من الناحية العملية ، من الضروري أحيانًا عرض بنية بيانات تشبه الشجرة في QComboBox.
المكون القياسي في Qt لبنية البيانات هذه هو QTreeView ، علاوة على ذلك ،
يمكن لـ QComboBox عرض هذا المكون بداخله ، ولكن كما هو الحال دائمًا ، توجد مساحات صغيرة في الوثائق ، لأنك لا تحتاج فقط إلى عرض الشجرة ، ولكن أيضًا تعيين العنصر الحالي الذي حدده المستخدم.
دعونا نرى كيفية القيام بذلك بشكل صحيح.
أولاً ، قم بإنشاء المكون نفسه ، الذي سيعرض البيانات ، لهذا نرثه من QComboBox ونمنحه الخصائص التي نحتاجها.
في الجزء المغلق من الفصل ، نعلن متغير m_view لفئة QTreeView ، والذي سيعرض الشجرة في QComboBox ، ويعيد تعريف دالات 2 المسؤولة عن سلوك المكون عند الفتح والإغلاق:
- تجاوز showPopup () باطل ؛ - يتم تنفيذه عندما يقوم المستخدم بتوسيع القائمة
- إلغاء hidePopup () باطل ؛ - يتم تنفيذه عندما يقوم المستخدم باختيار عنصر بالنقر فوقه
نضيف أيضًا وظيفة hideColumn (int n) ، والتي ستخفي الأعمدة التي تحتاجها في QTreeView ، لأنه إذا كان نموذجك يتكون من عدة أعمدة ، فسيعرضها QComboBox جميعًا (يستخدم المكون القياسي قائمة) ، والتي ستبدو قبيحة جدًا
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(); }
في المُنشئ ، قمنا بتعيين الشجرة التي نحتاج إلى البحث عنها بحيث تبدو "مضمنة" في QComboBox ، وإزالة الرؤوس ، وإخفاء عناصر التوسيع وتعيينها كعنصر عرض.
خدعة تثبيت عنصر محدد من قبل المستخدم في QComboBox بشكل صحيح هي وظائف showPopup () و hidePopup ().
نظرًا لأن QComboBox يعمل مع عرض نموذج "مسطح" ، فإنه لا يمكنه تعيين الفهرس الصحيح للعنصر المحدد من قبل المستخدم في نماذج الشجرة ، نظرًا لأنها تستخدم الفهرس المتعلق بالعنصر الأصلي لهذا:
showPopup ()
عنصر الجذر - نقوم بتعيين فهرس الجذر إلى فهرس نموذج غير صالح بحيث يعرض QComboBox جميع عناصر النموذج.
hidePopup ()
العنصر الجذر - نقوم بتعيين فهرس العنصر الرئيسي لعنصر النموذج المحدد من قبل المستخدم ، ثم بالنسبة للعنصر الرئيسي ، نقوم بتعيين عنصر المستخدم المحدد حسب الفهرس.
يتم استخدامه كله مثل هذا:
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(); }
