在PyQT5中的声明时设置事件的参数值?

时间:2016-06-20 15:46:01

标签: python python-2.7 pyqt pyqt5

背景

我正在PyQT5中编写一个简单的应用程序。主QWidgetQGridLayout,在视觉上结果应该是这样的:

        +-----------------------------------+
row1    |  QLabelA  |  QLabelB  |  QLabelC  |
        +-----------------------------------+
row2    |  QLabelA  |  QLabelB  |  QLabelC  |
        +-----------------------------------+
row3    |  QLabelA  |  QLabelB  |  QLabelC  |
        +-----------------------------------+
        ...

使用循环填充此QGridLayout,每次迭代代表一行,所以我有这样的东西:

row = 0
self.grid = QGridLayout()

while row < 10:
    filepath = 'icon.png'
    icon = QImage(filepath)
    QLabelA = QLabel()
    QLabelA.setPixmap(QPixmap.fromImage(icon))

    QLabelB = QLabel()
    QLabelB.setPixmap(QPixmap.fromImage(icon))

    QLabelC = QLabel()
    QLabelC.setPixmap(QPixmap.fromImage(icon))

    self.grid.addWidget(QLabelA, row, 0)
    self.grid.addWidget(QLabelB, row, 1)
    self.grid.addWidget(QLabelC, row, 2)

    row += 1

到目前为止,这很有效。

问题

我的目标是使这些QLabel中的每一个(视觉上都是图像)都有一个相关的动作,应该在用户对每个动作进行简单点击后触发。为此,我发现a property允许在点击一个对象后调用一个方法,所以我可以这样做:

QLabelA.mousePressedEvent = this.do_something

def do_something(self, event):
    ...

第一个问题很容易看出:我需要一种方法来识别哪个QLabel已被点击(即哪一行)。为此,我找到了一种向mousePressedEvent添加自定义参数的方法。让我们关注QLabelA字段,这些字段将在点击时调用clicked()方法:

QLabelA.mousePressEvent = lambda x: self.clicked(row)

def clicked(self, row):
    print row

以下是一个大问题:这些QLabelA字段中的每一个都依赖于row变量,并且在创建时不会对它们进行评估,而是在点击时进行评估。因此,如果用户点击第0行的QLabelAclicked()方法内,row将具有最后row值(即{的行数{1}})而不是定义时的那个。如果QGridLayout有5行,则用户点击的位置无关紧要,self.grid的值始终为5.

我尝试通过定义内部带有row值的列表来解决此限制,但它没有任何区别,因为它仍然依赖于点击时的row值。

问题

有没有办法让这项工作按预期工作,并在创建时分配传递给row方法的值而不是点击时间?任何不同的方法或方法也是受欢迎的。

1 个答案:

答案 0 :(得分:1)

你很接近使用lambda x:语句的解决方案,你只是缺少一个小块

使用Lambdas存储瞬态值

由于您的row变量发生了很大变化,因此您需要在创建函数时存储该值;正如您自己注意到的那样,您的self.clicked引用了当前的row。为了帮助你,你可以改变你的lambda:

# current: x is the event, row is looked up when the function is called
lambda x: self.clicked(row)

# New: x is the event, r is frozen when the function is created
lambda x, r=row: self.clicked(r)

这会导致每个lambda在创建时设置一个本地r,而不是在需要该函数时查找row