Question

Je créé un modèle qui liste les configurations existantes (Répétons le liste des « fichiers », car cela fait ici pas vraiment). Jusqu'à présent, cela fonctionne bien lorsqu'il est attaché à un QListView.

Exemple:

--- ListView ---
- file #1      -
- file #2      -
- file #3      -
- file #4      -
----------------

Est-il possible d'utiliser le même modèle pour un QMenu mis à jour dynamiquement?

Quelque chose comme:

Menu
-> Submenu #1
-> Submenu #2
-> File-submenu
  -> file #1
  -> file #2
  -> file #3
  -> file #4
-> Submenu #3

En bref: est-il possible de créer une liste des mises à jour (QActions dynamiquement regroupés dans la même QMenu) en fonction d'un modèle (dérivé de QAbstractListModel)

Était-ce utile?

La solution

Si votre objectif est simplement de mettre à jour votre menu actons avec le texte de l'élément qui sont disponibles dans le QAbstractListModel, alors la réponse est Oui.

Voici une façon ..

L'indice de l'article individuel peut être obtenue en utilisant la fonction suivante.

QModelIndex QAbstractListModel::index ( int row, int column = 0, 
const QModelIndex & parent = QModelIndex() ) const   [virtual]

Avec l'indice obtenu, les données peuvent être obtenues par,

 QVariant QModelIndex::data ( int role = Qt::DisplayRole ) const

Ensuite, on peut obtenir le availalble texte dans l'index à l'aide,

QString QVariant::toString () const

Maintenant, avec l'QString obtenu, vous pouvez ajouter une action au menu.

QAction * QMenu::addAction ( const QString & text )

La chose que vous devez faire est certain que, vous devriez être en mesure de traverser à travers tous les éléments du modèle, de sorte que vous pouvez obtenir l'indice de chaque élément. Hope it helps ..

Autres conseils

Malheureusement, il n'y a pas de classe QMenuView mais je trouve cette mise en œuvre prometteuse sur le net: QMenuView ( qmenuview.h , qmenuview.cpp ).

Pour répondre à votre question courte, oui, il y a. Mais vous devrez écrire vous-même.

La partie la plus facile serait de créer une sous-classe de QAbstractListModel.

Le plus dur serait lorsque vous créez votre propre point de vue. Qt vous permettra de créer votre propre point de vue, tout comme si vous deviez créer votre propre modèle, mais il deviendrait beaucoup plus complexe, puisque vous avez à poignée tout vous.

Il est tout à fait faisable dans un but spécifique, mais il est aussi beaucoup plus de travail que je pense que vous voulez. Alors, comme Gianni a dit, le cadre modèle de vue de Qt est pas destiné à être utilisé de cette façon.

Non

. Les modèles ne peuvent être utilisés avec des vues, selon le Model-View cadre des utilisations Qt.

Vous pouvez créer un élément de menu et de mettre en QListView à l'aide QWidgetAction. Bien sûr, ce menu ne peut pas avoir des sous-menus. L'exemple ci-dessous est en Python, mais j'espère que cela n'a pas d'importance dans ce cas.

from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import Qt


class QListViewMenu(QtWidgets.QMenu):
    """
    QMenu with QListView.
    Supports `activated`, `clicked`, `doubleClicked`. `setModel`.
    """
    max_visible_items = 16

    def __init__(self, parent=None):
        super().__init__(parent)
        self.listview = lv = QtWidgets.QListView()
        lv.setFrameShape(lv.NoFrame)
        lv.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        pal = lv.palette()
        pal.setColor(pal.Base, self.palette().color(pal.Window))
        lv.setPalette(pal)
        lv.setEditTriggers(lv.NoEditTriggers)  # disable edit on doubleclick

        act_wgt = QtWidgets.QWidgetAction(self)
        act_wgt.setDefaultWidget(lv)
        self.addAction(act_wgt)

        self.activated = lv.activated
        self.clicked = lv.clicked
        self.doubleClicked = lv.doubleClicked
        self.setModel = lv.setModel

        lv.sizeHint = self.size_hint
        lv.minimumSizeHint = self.size_hint
        lv.mousePressEvent = lambda event: None  # skip
        lv.mouseMoveEvent = lambda event: None  # skip
        lv.mouseReleaseEvent = self.mouse_release_event

    def size_hint(self):
        lv = self.listview
        width = lv.sizeHintForColumn(0)
        width += lv.verticalScrollBar().sizeHint().width()
        if isinstance(self.parent(), QtWidgets.QToolButton):
            width = max(width, self.parent().width())
        visible_rows = min(self.max_visible_items, lv.model().rowCount())
        return QtCore.QSize(width, visible_rows * lv.sizeHintForRow(0))

    def mouse_release_event(self, event):
        if event.button() == Qt.LeftButton:
            idx = self.listview.indexAt(event.pos())
            if idx.isValid():
                self.clicked.emit(idx)
            self.close()
        super(QtWidgets.QListView, self.listview).mouseReleaseEvent(event)


class Form(QtWidgets.QDialog):
    def __init__(self):
        super().__init__()
        words = "ability able about above accept according account across"
        model = QtCore.QStringListModel(words.split())
        # fake icons to take space
        def data(index, role):
            if role == Qt.DecorationRole:
                pixm = QtGui.QPixmap(40, 40)
                pixm.fill(Qt.transparent)
                return QtGui.QIcon(pixm)
            return QtCore.QStringListModel.data(model, index, role)
        model.data = data

        self.btn = btn = QtWidgets.QToolButton(self)
        btn.setText("QListView menu")
        btn.setPopupMode(btn.MenuButtonPopup)
        root_menu = QtWidgets.QMenu(btn)
        menu = QListViewMenu(btn)
        menu.setTitle('submenu')
        menu.setModel(model)
        menu.clicked.connect(self.item_clicked)
        root_menu.addMenu(menu)
        btn.setMenu(root_menu)

    def item_clicked(self, index):
        self.btn.menu().hide()
        print(index.data())

app = QtWidgets.QApplication([])
f = Form()
f.show()
app.exec()
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top