我创建了一个列出现有配置的模型(例如,它列出了“文件”,因为这里并不重要)。到目前为止,它连接到一个 QListView.

例子:

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

是否可以使用相同的模型进行动态更新 QMenu ?

就像是:

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

简而言之:是否有任何方法可以创建动态更新的列表 QActions(分为同一 QMenu)取决于 模型 (源自 QAbstractListModel) ?

有帮助吗?

解决方案

如果您的目标只是为了更新您的菜单acton QAbstractListModel, ,那么答案是肯定的。

这是一种方式..

可以使用以下功能获得单个项目的索引。

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

通过获得的索引,数据可以通过

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

然后,可以通过使用,

QString QVariant::toString () const

现在,使用获得的QString,您可以在菜单中添加一个操作。

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

您必须确保的是,您应该能够穿越模型中的所有项目,以便您可以获得每个项目的索引。希望能帮助到你..

其他提示

不幸的是,这儿没有 QMenuView 上课,但我发现网络上的这种有希望的实施: QMenuView (Qmenuview.H, qmenuview.cpp).

要回答您的简短问题,是的。但是您必须自己写。

简单的部分是创建一个QABSTRACTLISTMODEL的子类。

困难的部分是创建自己的视图时。 QT会让您创建自己的视图,就像您要创建自己的模型一样,但是它会变得更加复杂,因为您必须处理 一切 你自己。

对于特定目的来说,这完全是可行的,但它的工作比您想的要多得多。因此,就像吉安尼(Gianni)所说的那样,QT的模型视图框架并不是要使用这种方式。

否。模型只能与视图一起使用 模型视图 QT使用的框架。

您可以创建菜单项并放置 QListView 使用它 QWidgetAction. 。当然,此菜单不能具有子菜单。下面的示例是在Python中,但我希望在这种情况下没关系。

enter image description here

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()
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top