【问题标题】:Setting event's parameter value at declaration time in PyQT5?在 PyQT5 的声明时设置事件的参数值?
【发布时间】:2016-06-21 00:01:02
【问题描述】:

背景

我正在用 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

到目前为止,这工作得很好。

问题

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

QLabelA.mousePressedEvent = this.do_something

def do_something(self, event):
    ...

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

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

def clicked(self, row):
    print row

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

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

问题

有没有办法让这项工作按预期工作,并在创建时而不是点击时分配传递给 click() 方法的值?也欢迎任何不同的方法或方式来实现这一点。

【问题讨论】:

    标签: python python-2.7 pyqt pyqt5


    【解决方案1】:

    您的 lambda x: 语句非常接近解决方案,您只是缺少一小部分

    使用 Lambda 存储瞬态值

    由于你的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

    【讨论】:

    • 非常感谢!!这样就成功了,确实创建了 row 变量的本地副本正是我想要的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-23
    • 1970-01-01
    • 2021-11-02
    相关资源
    最近更新 更多