Frage

ich ein Modell erstellt, das die vorhandenen Konfigurationen auflisten (lassen Sie uns sagen, dass es „Dateien“ listet, da dies nicht wirklich hier Angelegenheit). Bisher funktioniert es gut, wenn sie ein QListView befestigt ist.

Beispiel:

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

Ist es möglich, das gleiche Modell für eine dynamisch aktualisierte QMenu zu benutzen?

So etwas wie:

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

Kurz gesagt: Gibt es eine Möglichkeit, eine Liste von dynamicaly aktualisiert QActions zu erstellen (gruppierte in die gleiche QMenu) in Abhängigkeit von einem Modell (von QAbstractListModel abgeleitet)

War es hilfreich?

Lösung

Wenn Ihr Ziel nur Ihr Menü Actons mit dem Artikeltext zu aktualisieren, die in den QAbstractListModel verfügbar sind, dann ist die Antwort Ja.

Hier ist eine Art und Weise ..

Index des Einzel Element kann mithilfe der folgenden Funktion erhalten werden.

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

Mit dem erhaltenen Index können die Daten erhalten werden, indem

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

Dann wird der Text availalble im Index kann durch die Verwendung erhalten werden,

QString QVariant::toString () const

Jetzt mit dem erhaltenen QString Sie eine Aktion zum Menü hinzufügen können.

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

Das, was Sie dafür sorgen müssen, ist, dass, sollten Sie in der Lage sein, alle zu durchqueren durch die Elemente in dem Modell, so dass Sie den Index der jede und jeder Punkt zu erhalten. Hoffe, es hilft ..

Andere Tipps

Leider gibt es keine QMenuView Klasse, aber ich fand diese vielversprechende Umsetzung im Internet: QMenuView ( qmenuview.h , qmenuview.cpp ).

Ihre kurze Frage zu beantworten, ja, es gibt. Aber Sie werden sich, es zu schreiben haben.

Der einfache Teil eine Unterklasse von QAbstractListModel zu erstellen wäre.

Der schwierige Teil wäre, wenn Sie Ihre eigene Ansicht erstellen. Qt können Sie Ihre eigene Ansicht zu erstellen, genau wie wenn Sie Ihr eigenes Modell erstellen waren, aber es wäre so viel komplexer geworden, da Sie Griff haben alles selbst.

Es ist durchaus machbar für einen bestimmten Zweck, aber es ist auch viel mehr Arbeit, als ich glaube, Sie wollen. So, wie Gianni sagt, Qt-Modell-Ansicht Rahmen ist nicht dazu gedacht, auf diese Art und Weise verwendet werden.

Nein. Die Modelle können nur mit Ansichten verwendet werden, gemäß dem Model-View Rahmen, dass Qt Anwendungen.

Sie können einen Menüpunkt anlegen und QListView hinein QWidgetAction verwenden. Natürlich kann dieses Menü hat nicht Untermenü. Das folgende Beispiel ist in Python, aber ich hoffe, es spielt keine Rolle, in diesem Fall.

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()
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top