QComboBox + QTreeView Tricks

En pratique, il est parfois nécessaire d'afficher une structure de données arborescente dans QComboBox.

Le composant standard dans Qt pour une telle structure de données est QTreeView, en outre,
QComboBox peut afficher ce composant à l'intérieur de lui-même, mais comme toujours, il y a de petits espaces dans la documentation, car vous devez non seulement afficher l'arborescence, mais également définir l'élément actuel sélectionné par l'utilisateur.

Voyons comment le faire correctement.

Tout d'abord, créez le composant lui-même, qui affichera les données, pour cela, nous héritons de QComboBox et lui donnons les propriétés dont nous avons besoin.

Dans la partie fermée de la classe, nous déclarons la variable m_view de la classe QTreeView, qui affichera l'arborescence dans la QComboBox, redéfinira 2 fonctions qui sont responsables du comportement du composant lors de l'ouverture et de la fermeture:

  • void showPopup () override; - exécuté lorsque l'utilisateur élargit la liste
  • void hidePopup () override; - effectué lorsque l'utilisateur sélectionne un élément en cliquant dessus

Nous ajoutons également la fonction hideColumn (int n), qui masquera les colonnes dont vous avez besoin dans QTreeView, car si votre modèle se compose de plusieurs colonnes, QComboBox les affichera toutes (le composant standard utilise une liste), qui aura l'air très moche

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(); } 

Dans le constructeur, nous définissons l'arborescence que nous devons rechercher afin qu'elle soit «intégrée» dans QComboBox, supprimons les en-têtes, masquons les éléments d'extension et définissons-la comme élément d'affichage.

L'astuce pour installer correctement un élément sélectionné par l'utilisateur dans une QComboBox est les fonctions showPopup () et hidePopup ().

Étant donné que QComboBox fonctionne avec une vue de modèle «plate», il ne peut pas définir l'index correct de l'élément sélectionné par l'utilisateur dans les modèles d'arbre, car ils utilisent pour cela l'index relatif à l'élément parent:
showPopup ()

élément racine - nous définissons l'index racine sur un index de modèle non valide afin que QComboBox affiche tous les éléments du modèle.
hidePopup ()

élément racine - nous définissons l'index du parent de l'élément de modèle sélectionné par l'utilisateur, puis par rapport à l'élément parent, nous définissons l'élément utilisateur sélectionné par index.

Il est utilisé comme ceci:

 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/fr420977/


All Articles