使用模型作为 QMenu 的源

发布于 2024-09-08 02:03:50 字数 552 浏览 10 评论 0原文

我创建了一个模型,其中列出了现有配置(假设它列出了“文件”,因为这在这里并不重要)。到目前为止,它在附加到 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

简而言之:有什么方法可以根据模型QAction列表(分组到相同的QMenu) >(源自QAbstractListModel)?

I created a model which list the existing configurations (let's say it lists "files", as this doesn't really matter here). So far, it works well when attached to a QListView.

Example:

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

Is it possible to use the same model for a dynamically updated QMenu ?

Something like:

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

In short: is there any way to create a list of dynamicaly updated QActions (grouped into the same QMenu) depending on a model (derived from QAbstractListModel) ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

孤寂小茶 2024-09-15 02:03:51

不幸的是,没有 QMenuView 类,但我在网上发现了这个有希望的实现:QMenuView (qmenuview.hqmenuview .cpp)。

Unfortunately there is no QMenuView class but I found this promising implementation on the net: QMenuView (qmenuview.h, qmenuview.cpp).

薄情伤 2024-09-15 02:03:51

如果您的目标只是使用 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 )

您必须确保的是,您应该能够遍历 Model 中的所有项目,以便获得每个项目的索引。希望有帮助..

If your objective is just to update your menu actons with the item text that are available in the QAbstractListModel, then the answer is Yes.

Here is a way..

Individual item's index can be obtained by using the following function.

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

With the obtained index, the data can be obtained by,

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

Then the text availalble in the index can be obtained by using,

QString QVariant::toString () const

Now with the obtained QString you can add an action to the menu.

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

The thing you have to make sure is that, you should be able to traverse through all the items in the Model, so that you can obtain the index of the each and every item. Hope it helps..

給妳壹絲溫柔 2024-09-15 02:03:51

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

最简单的部分是创建 QAbstractListModel 的子类。

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

对于特定目的来说,这是完全可行的,但它也比我认为你想要的要多得多。因此,正如 Gianni 所说,Qt 的模型视图框架不适合以这种方式使用。

To answer your short question, yes, there is. But you'll have to write it yourself.

The easy part would be to create a subclass of QAbstractListModel.

The hard part would be when you create your own view. Qt will let you create your own view, just like if you were to create your own model, but it would become so much more complex, since you've got to handle everything yourself.

It's entirely doable for a specific purpose, but it's also much more work than I think you want. So, like Gianni was saying, Qt's model-view framework isn't meant to be used this way.

知你几分 2024-09-15 02:03:51

不可以。模型只能与视图一起使用,根据 模型视图 Qt 使用的框架。

No. Models can only be used with Views, as per the Model-View framework that Qt uses.

吖咩 2024-09-15 02:03:51

您可以创建一个菜单项并使用QWidgetActionQListView放入其中。当然这个菜单不能有子菜单。下面的示例是用 Python 编写的,但我希望在这种情况下这并不重要。

输入图片此处描述

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()

You can create a menu item and put QListView into it using QWidgetAction. Of course this menu cannot have submenus. The example below is in Python, but I hope it doesn't matter in this case.

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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文