Pregunta

He creado un modelo que enumeran las configuraciones existentes (digamos que enumera "archivos", ya que en realidad no importa aquí). Hasta el momento, funciona bien cuando está conectado a un QListView.

Ejemplo:

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

¿Es posible utilizar el mismo modelo para un QMenu actualizada dinámicamente?

Algo así como:

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

En resumen:? ¿Hay alguna manera de crear una lista de QActions dynamicaly actualizadas (agrupados en el mismo QMenu) en función de un modelo (derivado de QAbstractListModel)

¿Fue útil?

Solución

Si su objetivo es sólo para actualizar sus Actons menú con el elemento de texto que están disponibles en el QAbstractListModel, entonces la respuesta es Sí.

Esta es una manera ..

índice de elemento individual se puede obtener mediante el uso de la siguiente función.

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

Con el índice obtenido, los datos pueden ser obtenidos por,

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

A continuación, el availalble texto en el índice se puede obtener mediante el uso de,

QString QVariant::toString () const

Ahora con los obtenidos QString se puede añadir una acción al menú.

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

Lo que usted tiene que asegurarse de que es, debe ser capaz de recorrer a través de todos los elementos en el modelo, por lo que se puede obtener el índice de la cada elemento. Esperamos que ayude ..

Otros consejos

Desafortunadamente no existe una clase QMenuView pero he encontrado esta aplicación prometedor en la red: QMenuView ( qmenuview.h , qmenuview.cpp ).

Para responder a su pregunta corta, sí, lo hay. Sin embargo, usted tiene que escribir por sí mismo.

La parte fácil sería crear una subclase de QAbstractListModel.

La parte difícil sería al crear su propio punto de vista. Qt le permitirá crear su propio punto de vista, al igual que si tuviera que crear su propio modelo, pero sería convertido en mucho más complejo, ya que tienes a mango todo a ti mismo.

Es totalmente factible para un propósito específico, pero también es mucho más trabajo que creo que quieres. Por lo tanto, al igual que Gianni estaba diciendo, marco modelo-vista de Qt no está destinado a ser utilizado de esta manera.

No. Modelos sólo pueden ser utilizados con Vistas, según la Modelo-Vista marco que utiliza Qt.

Se puede crear un elemento de menú y poner QListView en ella usando QWidgetAction. Por supuesto, este menú no puede tener submenús. El siguiente ejemplo es en Python, pero espero que no importa en este caso.

introducir descripción de la imagen aquí

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()
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top