PyQt5 循环构建菜单

PyQt5 Build Menus in a Loop

我有以下在 PyQt5 中在按钮上构建菜单的示例。虽然这很有效,但是当您要构建数百个菜单时,它会很麻烦。有没有办法在 for 循环中执行此操作?

    inputMenu_0 = QMenu()
    inputMenu_0.triggered.connect(lambda x: self.inputPb_0.setText(x.text()))
    self.add_menu(self.inputs, inputMenu_0)
    self.inputPb_0.setMenu(inputMenu_0)

使用上述代码段的工作示例。

    #!/usr/bin/python3

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QMenu, QWidget
from PyQt5.QtGui import QIcon

class Window(QMainWindow):
    def __init__(self):
        super(Window, self).__init__()
        self.setGeometry(50, 50, 500, 300)
        self.setWindowTitle("PyQT5 Minimal!")
        self.central_widget = QWidget(self)
        self.central_widget.setFocus()
        self.setCentralWidget(self.central_widget)

        self.inputPb_0 = QPushButton('Button 0', self)
        self.inputPb_0.move(15, 10)
        self.inputPb_1 = QPushButton('Button 1', self)
        self.inputPb_1.move(15, 40)

        self.inputs = [{'Homing':['X Home', 'Y Home', 'Z Home']},
            {'Jog':['Jog A', 'Jog B', 'Jog C', 'Jog U', 'Jog V', 'Jog W', 'Jog X', 'Jog Y', 'Jog Z']},
            {'Coolant':['Flood', 'Mist']},
            {'Digital':['Digital 0', 'Digital 1', 'Digital 2', 'Digital 3']}
        ]

        inputMenu_0 = QMenu()
        inputMenu_0.triggered.connect(lambda x: self.inputPb_0.setText(x.text()))
        self.add_menu(self.inputs, inputMenu_0)
        self.inputPb_0.setMenu(inputMenu_0)

        inputMenu_1 = QMenu()
        inputMenu_1.triggered.connect(lambda x: self.inputPb_1.setText(x.text()))
        self.add_menu(self.inputs, inputMenu_1)
        self.inputPb_1.setMenu(inputMenu_1)

        self.show()

    def add_menu(self, data, menu_obj):
        if isinstance(data, dict):
            for k, v in data.items():
                sub_menu = QMenu(k, menu_obj)
                menu_obj.addMenu(sub_menu)
                self.add_menu(v, sub_menu)
        elif isinstance(data, list):
            for element in data:
                self.add_menu(element, menu_obj)
        else:
            action = menu_obj.addAction(data)
            action.setIconVisibleInMenu(False)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    GUI = Window()
    sys.exit(app.exec_())

此代码将 运行 但两个按钮的连接都会转到第二个。如果您 select 按钮 0 中的菜单项,按钮 1 中的文本会发生变化。

        self.inputMenu_0 = QMenu()
    self.inputMenu_1 = QMenu()
    for i in range(2):
        getattr(self, 'inputMenu_' + str(i)).triggered.connect(lambda x: getattr(self, 'inputPb_' + str(i)).setText(x.text()))
        self.add_menu(self.inputs, getattr(self, 'inputMenu_' + str(i)))
        getattr(self, 'inputPb_' + str(i)).setMenu(getattr(self, 'inputMenu_' + str(i)))

以下代码片段有效,但我不知道如何在循环中编写连接代码。

    self.inputMenu_0 = QMenu()
self.inputMenu_0.triggered.connect(lambda x: self.inputPb_0.setText(x.text()))
self.inputMenu_1 = QMenu()
self.inputMenu_1.triggered.connect(lambda x: self.inputPb_1.setText(x.text()))
for i in range(2):
    #getattr(self, 'inputMenu_' + str(i)).triggered.connect(lambda x: getattr(self, 'inputPb_' + str(i)).setText(x.text()))
    self.add_menu(self.inputs, getattr(self, 'inputMenu_' + str(i)))
    getattr(self, 'inputPb_' + str(i)).setMenu(getattr(self, 'inputMenu_' + str(i)))

为避免这些混淆,最好限制 getattr 的使用,这样我们将保留更具可读性的代码,从而减少混淆。

for i in range(2):
    button = getattr(self, "inputPb_{}".format(i))
    menu = QMenu()
    menu.triggered.connect(lambda action, button=button: button.setText(action.text()))
    self.add_menu(self.inputs, menu)
    button.setMenu(menu)