حيل QComboBox + QTreeView

من الناحية العملية ، من الضروري أحيانًا عرض بنية بيانات تشبه الشجرة في 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(); } 

Source: https://habr.com/ru/post/ar420977/


All Articles