Как получить название элемента QMenu при нажатии? - PullRequest
0 голосов
/ 27 сентября 2018

У меня есть несколько действий в 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(), чтобы присвоить действию более понятное имя для метода получения, но, похоже, это не работает должным образом.

1 Ответ

0 голосов
/ 27 сентября 2018

Возможным решением является использование метода 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_())

Если вы собираетесь подключить всеQAction с 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_())

Обновление:

Сигнал QAction triggered отличается от сигнала QMenu triggered, в случае первого он посылает логическое значение, которое указывает, если проверен QAction (по умолчанию QActionне проверяемый, если вы хотите активировать его, вы должны использовать setCheckable(True)), а во втором случае он отправляет нажатой QAction, который принадлежит QMenu.Вот почему вы всегда получаете False, если вы не хотите иметь эту проблему, вы должны использовать мой первый метод, используя sender().С другой стороны, в Qt очень редко вам придется использовать try-исключение, в действительности вы никогда не должны использовать его в мире Qt, поскольку это требует дополнительных затрат, которых не желает Qt, а с другой стороны, оно скрывает причину.из ошибок, в качестве рекомендации используйте try-кроме, если нет другого решения, и в случае 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_())
...