在 QMenu 中,如何使子菜单像 QAction 一样可调用

In a QMenu, how to make a submenu callable like a QAction

我正在尝试实现类似于 classification 树的东西,我在其中右键单击 QTableWidget 中的一行以调用菜单,然后为其选择一个 class 标签。我的标签树是这样的:

这里ClassA,ClassA2显然是通过QMenu.addMenu()方法添加的,在这个方法中是不可调用的。 ClassA1、ClassA3、ClassB是通过QMenu.addAction()方法添加的,可调用。所以我想知道有没有办法让子菜单像可以触发的 QAction 一样可调用?或者有什么更好的方法可以达到我的设计目的?

顺便说一句,我认为 aboutToShow() 信号不起作用,因为该信号是在子菜单显示而不是被单击时发出的。

代码:

class ClassMenu(QMenu):

    def __init__(self):
        
        super(ClassMenu, self).__init__()
        class_A = self.addMenu("ClassA")
        class_A1 = class_A.addAction("ClassA1")
        class_A2 = class_A.addMenu("ClassA2")
        class_A3 = class_A2.addAction("ClassA3")
        class_B = self.addAction("ClassB")
        
        class_A1.triggered.connect(self.onMenuClicked)
        class_A3.triggered.connect(self.onMenuClicked)
        class_B.triggered.connect(self.onMenuClicked)

    def onMenuClicked(self):
        print(self.sender().text())

一个可能的解决方案是覆盖 mousePressEvent 并验证与该位置关联的 QAction 是否具有与其关联的 QMenu:

from PyQt5.QtWidgets import QApplication, QMenu


class ClassMenu(QMenu):
    def __init__(self):
        super(ClassMenu, self).__init__()
        class_A = self.addMenu("ClassA")
        class_A1 = class_A.addAction("ClassA1")
        class_A2 = class_A.addMenu("ClassA2")
        class_A3 = class_A2.addAction("ClassA3")
        class_B = self.addAction("ClassB")

        class_A1.triggered.connect(self.onActionClicked)
        class_A3.triggered.connect(self.onActionClicked)
        class_B.triggered.connect(self.onActionClicked)

        print(class_A.menuAction())

    def onActionClicked(self):
        print(self.sender().text())

    def onMenuClicked(self, menu):
        print(menu.title())

    def mousePressEvent(self, event):
        super().mousePressEvent(event)
        action = self.actionAt(event.pos())
        if not action:
            return
        menu = action.menu()
        if menu:
            self.onMenuClicked(menu)


def main():
    app = QApplication([])
    menu = ClassMenu()
    menu.move(100, 100)
    menu.exec_()


if __name__ == "__main__":
    main()