如何在单击时获取 QMenu 项目的名称?

art*_*son 6 python pyqt qmenu python-3.x pyqt5

QMenu我在尝试连接到单个方法时有一些操作;还有一些不相关的其他操作。

import sys
from PyQt5.QtWidgets import *


class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()

        layout = QGridLayout(self)
        self.menu_bar = QMenuBar()
        self.menu = QMenu('MENU', self)

        self.menu_action = QAction('Option #1', self)
        self.menu_action.setData('option1')
        self.menu_action.triggered.connect(self.actionClicked)

        self.menu.addAction(self.menu_action)
        self.menu_bar.addMenu(self.menu)
        layout.addWidget(self.menu_bar)

    def actionClicked(self, action):
        print(action)

        try:
            print(action.text())
        except AttributeError as e:
            print(e)

        try:
            print(action.data())
        except AttributeError as e:
            print(e)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = Window()
    window.setGeometry(600, 100, 300, 100)
    window.show()
    sys.exit(app.exec_())
Run Code Online (Sandbox Code Playgroud)

我想知道在调用该方法时如何知道单击了哪些操作。目前,我正在尝试self.menu_action.setData()为该操作提供一个更清晰的接收方法名称,但这似乎无法正常工作。

eyl*_*esc 11

一种可能的解决方案是使用sender()返回QObject发出信号的方法,在本例中为QAction

import sys
from PyQt5 import QtCore, QtWidgets


class Window(QtWidgets.QWidget):
    def __init__(self):
        super(Window, self).__init__()

        layout = QtWidgets.QGridLayout(self)
        menubar = QtWidgets.QMenuBar()
        filemenu = menubar.addMenu('MENU')

        filemenu.addAction('Option #1', self.actionClicked)
        filemenu.addAction('Option #2', self.actionClicked)
        layout.addWidget(menubar)

    @QtCore.pyqtSlot()
    def actionClicked(self):
        action = self.sender()
        print('Action: ', action.text())


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.setGeometry(600, 100, 300, 100)
    window.show()
    sys.exit(app.exec_())
Run Code Online (Sandbox Code Playgroud)

如果您要连接 的所有QActions,QMenu则可以使用triggered的信号QMenu,这会发送QAction按下的 。

import sys
from PyQt5 import QtCore, QtWidgets


class Window(QtWidgets.QWidget):
    def __init__(self):
        super(Window, self).__init__()

        layout = QtWidgets.QGridLayout(self)
        menubar = QtWidgets.QMenuBar()
        filemenu = menubar.addMenu('MENU')
        filemenu.triggered.connect(self.actionClicked)
        filemenu.addAction('Option #1')
        filemenu.addAction('Option #2')
        layout.addWidget(menubar)

    @QtCore.pyqtSlot(QtWidgets.QAction)
    def actionClicked(self, action):
        print('Action: ', action.text())


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.setGeometry(600, 100, 300, 100)
    window.show()
    sys.exit(app.exec_())
Run Code Online (Sandbox Code Playgroud)

更新:

QAction triggered信号与该信号不同QMenu triggered,在第一种情况下,它发送一个布尔值,指示是否QAction选中(默认情况下 aQAction不可选中,如果要激活它,则必须使用setCheckable(True)),在第二种情况下,它发送发送QAction属于 的被按下的QMenu。这就是为什么你总是得到 False,如果你不想遇到这个问题,你必须使用我的第一个方法使用sender(). 另一方面,在 Qt 中,您很少需要使用 try- except,实际上您不应该在 Qt 的世界中使用它,因为这会产生 Qt 不希望的额外成本,另一方面它隐藏了原因的错误,作为建议,当没有其他解决方案时使用 try- except ,并且在 Qt 的情况下几乎总是有另一个选择。

import sys
from PyQt5.QtWidgets import *


class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()
        layout = QGridLayout(self)
        self.menu_bar = QMenuBar()
        self.menu = QMenu('MENU', self)

        self.menu_action = QAction('Option #1', self)
        self.menu_action.setData('option1')
        self.menu_action.triggered.connect(self.actionClicked)

        self.menu.addAction(self.menu_action)
        self.menu_bar.addMenu(self.menu)
        layout.addWidget(self.menu_bar)

    def actionClicked(self, checked):
        action = self.sender()
        print(action.text())
        print(action.data())


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = Window()
    window.setGeometry(600, 100, 300, 100)
    window.show()
    sys.exit(app.exec_())
Run Code Online (Sandbox Code Playgroud)