Domanda

Ho creato un modello che elenca le configurazioni esistenti (diciamo che elenca "file", in quanto questo non importa qui). Finora, funziona bene se collegato a un QListView.

Esempio:

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

E 'possibile utilizzare lo stesso modello per un QMenu aggiornato dinamicamente?

Qualcosa di simile:

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

In breve: esiste un modo per creare un elenco di QActions dynamicaly aggiornati (raggruppati nella stessa QMenu) in funzione di un modello (derivato da QAbstractListModel)

È stato utile?

Soluzione

Se il vostro obiettivo è solo quello di aggiornare i Actons menu con il testo della voce che sono disponibili nel QAbstractListModel, allora la risposta è Sì.

Ecco un modo ..

indice dell'elemento Persona può essere ottenuta utilizzando la seguente funzione.

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

Con l'indice ottenuto, i dati possono essere ottenuti,

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

Poi l'availalble testo l'indice può essere ottenuto utilizzando,

QString QVariant::toString () const

Ora, con l'ottenuto QString è possibile aggiungere un'azione al menu.

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

La cosa che dovete fare in modo che sia, si dovrebbe essere in grado di attraversare attraverso tutti gli elementi del modello, in modo da poter ottenere l'indice del ogni singolo elemento. Speranza che aiuta ..

Altri suggerimenti

Purtroppo non esiste una categoria QMenuView ma ho trovato questa implementazione promettendo in rete: QMenuView ( qmenuview.h , qmenuview.cpp ).

Per rispondere alla tua domanda breve, sì, c'è. Ma dovrete scrivere voi stessi.

La parte più semplice sarebbe quella di creare una sottoclasse di QAbstractListModel.

La parte più difficile sarebbe quando si crea il proprio punto di vista. Qt vi permetterà di creare il vostro punto di vista, proprio come se si dovesse creare il proprio modello, ma sarebbe diventato così molto più complessa, dal momento che hai avuto modo di maniglia tutto da soli.

E 'del tutto fattibile per uno scopo specifico, ma è anche molto più lavoro di quanto Penso che si desidera. Così, come Gianni stava dicendo, quadro model-view di Qt non è pensato per essere utilizzato in questo modo.

No. I modelli possono essere utilizzati solo con Vista, come da Model-View un'infrastruttura che utilizza Qt.

È possibile creare una voce di menu e metterlo QListView in esso utilizzando QWidgetAction. Naturalmente questo menu non può avere sottomenu. L'esempio che segue è in Python, ma spero che non importa in questo caso.

entrare descrizione dell'immagine qui

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()
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top