【问题标题】:How to get the name of a QMenu Item when clicked?单击时如何获取 QMenu 项的名称?
【发布时间】:2019-03-02 17:20:12
【问题描述】:

我在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_())

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

【问题讨论】:

    标签: python python-3.x pyqt pyqt5 qmenu


    【解决方案1】:

    一种可能的解决方案是使用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_())
    

    如果您要连接QMenu 的所有QActions,那么您可以使用QMenutriggered 信号,这会发送被按下的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_())
    

    更新:

    QAction triggered 信号与QMenu triggered 信号不同,在第一个信号的情况下,它发送一个布尔值,指示是否检查了QAction(默认情况下为@987654336 @ 是不可检查的,如果你想激活它,你必须使用setCheckable(True)),在第二种情况下,它发送属于QMenu 的被按下的QAction。这就是为什么你总是得到 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_())
    

    【讨论】:

    • 我认为第一个选项应该很好用。我最初尝试使用 `.setData('Option #1')',但它所做的只是在方法中返回 false;我什么都做不了。
    • @AaronTomason 你在哪里做 setData() ?,如果我的回答对你有帮助,别忘了把它标记为正确
    • 我将菜单操作之一设置为self.option1 = QAction1('Option #1', self) 然后self.option1.setData(QVariant('option1')) 并使用self.option1.triggered.connect(self.actionClicked) 连接它。当我尝试打印动作时,它只是一个False 值。
    • @AaronTomason 我明白你是怎么用的,但是既然你得到了False,也就是你得做print(xxx)之类的东西,xxx是什么?
    • 我试过print(action)。当我尝试使用print(action.text())print(action.data()) 时,python 说布尔对象没有 xxx。
    猜你喜欢
    • 2019-11-23
    • 1970-01-01
    • 2021-12-30
    • 2020-04-05
    • 2012-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多