【问题标题】:How do I make a context menu for each item in a QListWidget?如何为 QListWidget 中的每个项目创建上下文菜单?
【发布时间】:2018-07-31 02:57:00
【问题描述】:

我正在开发一个 QGIS 插件,其中的 UI 是用 PyQt 制作的。我有一个 QListWidget 和一个填充它的函数。我想为每个项目添加一个上下文菜单,只有一个选项:打开另一个窗口。

我在搜索信息时遇到了麻烦,因为大部分信息仅适用于 PyQt4,而我使用的是版本 5。我想在其上添加上下文菜单的 QListWidget 是 ds_list_widget。这是一些相关的代码。

FORM_CLASS, _ = uic.loadUiType(os.path.join(
    os.path.dirname(__file__), 'dialog_base.ui'))

class Dialog(QDialog, FORM_CLASS):
    def __init__(self, parent=None):
        ...
        self.p_list_widget = self.findChild(QListWidget, 'projects_listWidget') 
        self.p_list_widget.itemClicked.connect(self.project_clicked)
        self.ds_list_widget = self.findChild(QListWidget, 'datasets_listWidget')        
        self.ds_list_widget.itemClicked.connect(self.dataset_clicked)
        ...


    def project_clicked(self, item):
        self.fill_datasets_list(str(item.data(Qt.UserRole)))        
        self.settings.setValue('projectIdValue', str(item.data(Qt.UserRole)))

    def fill_datasets_list(self, project_id):
        self.ds_list_widget.clear()
        dataset_list = self.anotherClass.fetch_dataset_list(project_id)

        for dataset in dataset_list:
            #Query stuff from remote
            ...
            item = QListWidgetItem(ds_name, self.ds_list_widget)
            item.setIcon(self.newIcon(ds_img))
            item.setData(Qt.UserRole, ds_id)
            self.ds_list_widget.addItem(item)
            self.ds_list_widget.setIconSize(self.iconSize)

【问题讨论】:

标签: python contextmenu pyqt5 qlistwidget


【解决方案1】:

由于您的列表小部件是由 Qt 设计器创建的,因此在其上安装 event-filter 并捕获上下文菜单事件可能是最简单的。有了这些,剩下的就很简单了——这是一个简单的演示:

import sys
from PyQt5 import QtCore, QtWidgets

class Dialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(Dialog, self).__init__()
        self.listWidget = QtWidgets.QListWidget()
        self.listWidget.addItems('One Two Three'.split())
        self.listWidget.installEventFilter(self)
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.listWidget)

    def eventFilter(self, source, event):
        if (event.type() == QtCore.QEvent.ContextMenu and
            source is self.listWidget):
            menu = QtWidgets.QMenu()
            menu.addAction('Open Window')
            if menu.exec_(event.globalPos()):
                item = source.itemAt(event.pos())
                print(item.text())
            return True
        return super(Dialog, self).eventFilter(source, event)

if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    window = Dialog()
    window.setGeometry(600, 100, 300, 200)
    window.show()
    sys.exit(app.exec_())

PS:

您还应该注意这样的代码:

self.p_list_widget = self.findChild(QListWidget, 'projects_listWidget')

完全没有必要。来自 Qt Designer 的所有小部件都使用对象名称作为属性自动添加到表单类。所以你的代码可以简化为:

self.projects_listWidget.itemClicked.connect(self.project_clicked)
self.datasets_listWidget.itemClicked.connect(self.dataset_clicked)

没有必要使用findChild

【讨论】:

  • 非常感谢!事实证明,我的老板告诉我的事情是错误的,所以没有必要再做上下文菜单了。但是PS真的很有用!而且这个例子肯定会对我自己的项目有所帮助。
【解决方案2】:

除了上面的答案,你还可以设置多个QAction()子菜单项来做多个事情。就像普通菜单一样。

一种方法是编辑您的eventFilter,使menu.exec() 成为一个变量:

def eventFilter(self, source, event):
    if (event.type() == QtCore.QEvent.ContextMenu and source is self.listWidget):
        menu = QtWidgets.QMenu()
        open_window_1 = QAction("Open Window 1")
        open_window_2 = QAction("Open Window 2")
        menu.addAction(open_window_1)
        menu.addAction(open_window_2)
        menu_click = menu.exec(event.globalPos())
        
        try:
            item = source.itemAt(event.pos())
        except Exception as e:
            print(f"No item selected {e}")

        if menu_click == open_window_1 :
                print("Opening Window 1...")
                # Your code here
        if menu_click == open_window_2 :
                print("Opening Window 2...")
                # Your code here

        # and so on... You can now add as many items as you want
        return True
    return super(Dialog, self).eventFilter(source, event)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-24
    • 1970-01-01
    • 1970-01-01
    • 2014-12-15
    相关资源
    最近更新 更多