在循环中创建 PyQt5 按钮:所有按钮触发相同的回调

Creating PyQt5 buttons in a loop: all buttons trigger the same callback

我应该提一下,我已经阅读了这些内容,但我仍然无法实现我的目标:

[Using a dictionary in a for loop to create buttons doesn't work

[QtCore.QObject.connect in a loop only affects the last instance

我的目标是 linux 'launcher' 申请。按钮创建、放置等工作非常顺利,但有一个问题 - 所有按钮触发相同的回调 - 最后一个在按钮创建循环中连接。

下面是脚本的基本版本,用于说明我要执行的操作:

class App(QMainWindow):

    def launch(self, filepath):
        subprocess.run(filepath)


    def __init__(self):
        super(App, self).__init__()

        for btn in matrix:

            filepath = matrix[btn]['path']
            icon = matrix[btn]['setIcon']
            posx = matrix[btn]['posx']
            posy = matrix[btn]['posy']

            matrix[btn] = QToolButton(self)
            matrix[btn].setIcon(QIcon(icon))
            matrix[btn].setIconSize(QSize(64, 64))
            matrix[btn].resize(100, 100)
            matrix[btn].move(posx, posy)
            matrix[btn].clicked.connect(lambda launch: self.launch(filepath))

        self.initUI()


    def initUI(self):

        self.setGeometry(150, 150, 1250, 650)
        self.setWindowTitle('LinuxLauncher')

        self.show()


    if __name__ == '__main__':

        app = QApplication(sys.argv)
        ex = App()
        sys.exit(app.exec_())

我知道有答案,但我已经花了好几个小时了 - 如果有人能帮我解决这个问题,我将不胜感激 - 谢谢!

我不明白矩阵是什么类型的结构,但我认为它相当于一个字典列表。

问题是您必须将参数作为参数传递给分配它的 lambda 函数,点击信号将布尔值作为参数,指示按钮是否被选中(默认情况下此 属性 被禁用,因此该值为假),您必须添加另一个参数。

class App(QMainWindow):
    def launch(self, filepath):
        subprocess.run(filepath)

    def __init__(self):
        super(App, self).__init__()

        matrix = [{"path": "path1", "setIcon": "icon1", "posx": 0, "posy": 0}, 
        {"path": "path2", "setIcon": "icon2", "posx": 0, "posy": 150},
        {"path": "path3", "setIcon": "icon3", "posx": 0, "posy": 300}]

        for value in matrix:

            filepath = value['path']
            icon =  value['setIcon']
            posx = value['posx']
            posy = value['posy']

            btn = QToolButton(self)
            btn.setIcon(QIcon(icon))
            btn.setIconSize(QSize(64, 64))
            btn.resize(100, 100)
            btn.move(posx, posy)
            btn.clicked.connect(lambda checked, arg=filepath: self.launch(arg))

        self.initUI()

    def initUI(self):
        self.setGeometry(150, 150, 1250, 650)
        self.setWindowTitle('LinuxLauncher')
        self.show()