如何将上下文菜单添加到 PyQt5 中的上下文菜单?

How to add a context menu to a context menu in PyQt5?

我正在使用 PyQt5 在 python 中构建一个 GUI,我需要当我右键单击上下文菜单中的一个选项时,它会显示另一个上下文菜单,如图所示...

(我知道我可以在其中一个选项中嵌套菜单,但这不是我想要的)

上下文菜单不区分右击和左击。

我认为要实现这一点有两个问题...

  1. 我不知道如何防止右键单击触发PyQt5.QtWidgets.QAction
  2. 第二个问题是,通常创建上下文菜单的步骤之一是在小部件上使用 .installEventFilter() 方法,但在这种情况下,您应该在类型为 PyQt5.QtWidgets.QAction

我知道我所要求的实现起来很复杂,但如果您能给我一些信息以帮助我实现它,我将不胜感激。

在这里我给你留下了一个 GUI 的代码,它带有一个安装了上下文菜单的小部件...

from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenu
import sys
from PyQt5.QtCore import QEvent


class MyWindow(QMainWindow):
    def __init__(self):
        super(MyWindow, self).__init__()
        self.createWidgets()

    def createWidgets(self):
        self.my_button = QtWidgets.QPushButton(self)
        self.my_button.setText("My Widget")
        self.my_button.installEventFilter(self)

    def eventFilter(self, source, event):
        if event.type() == QEvent.ContextMenu and source is self.my_button:
            menu = QMenu()

            action1 = menu.addAction("Option 1")
            action2 = menu.addAction("Option 2")
            action3 = menu.addAction("Option 3")

            selected_action = menu.exec_(event.globalPos())

            if selected_action == action1:
                print("You have selected the first option")
            if selected_action == action2:
                print("You have selected the second option")
            if selected_action == action3:
                print("You have selected the third option")

        return super().eventFilter(source, event)




def showWindow():
    app = QApplication(sys.argv)
    window = MyWindow()
    window.show()
    sys.exit(app.exec_())

showWindow()

在按钮上安装事件过滤器是不够的,你当然不能在QAction上安装它,它永远不会触发鼠标事件,因为它没有继承自QWidget。您必须在菜单本身上安装过滤器。

为了允许正确跟踪菜单(并对它们的事件做出正确反应),最好也保留更多对菜单的静态引用。

显然,您可以创建 QMenu 的子类,这可能会使事情变得更容易。

class MyWindow(QMainWindow):
    def __init__(self):
        super(MyWindow, self).__init__()
        self.createWidgets()

    def createWidgets(self):
        self.my_button = QtWidgets.QPushButton(self)
        self.my_button.setText("My Widget")

        self.buttonMenu = QMenu(self.my_button)
        self.buttonMenu.addAction("Option 1")
        self.buttonMenu.addAction("Option 2")
        self.buttonMenu.addAction("Option 3")

        self.subMenu = QMenu(self.buttonMenu)
        self.subMenu.addAction("Sub Option 1")
        self.subMenu.addAction("Sub Option 2")
        self.subMenu.addAction("Sub Option 3")

        self.my_button.installEventFilter(self)
        self.buttonMenu.installEventFilter(self)

    def eventFilter(self, source, event):
        if event.type() == QEvent.ContextMenu:
            if source == self.my_button:
                self.buttonMenu.exec_(event.globalPos())
                return True
            elif source == self.buttonMenu:
                self.subMenu.exec_(event.globalPos())
                return True

        return super().eventFilter(source, event)