我尝试使用 PyQt4 构建一个计算器,但从按钮连接“clicked()”信号无法按预期工作。
我为 for 循环内的数字创建按钮,然后尝试连接它们。
def __init__(self):
for i in range(0,10):
self._numberButtons += [QPushButton(str(i), self)]
self.connect(self._numberButtons[i], SIGNAL('clicked()'), lambda : self._number(i))
def _number(self, x):
print(x)
当我单击按钮时,所有按钮都会打印出“9”。
为什么会这样?我该如何解决这个问题?
这就是 Python 中定义作用域、名称查找和闭包的方式。
Python 仅通过赋值和函数参数列表在命名空间中引入新的绑定。i
因此实际上并未在名称空间中定义lambda
,但是在命名空间中__init__()
。名称查找i
在 lambda 中最终会出现在命名空间中__init__()
, where i
最终必然会9
。这称为“关闭”。
您可以通过传递来解决这些确实不是很直观(但定义明确)的语义i
作为具有默认值的关键字参数。如前所述,参数列表中的名称在本地命名空间中引入了新的绑定,因此i
在 - 的里面lambda
然后变得独立于i
in .__init__()
:
self._numberButtons[i].clicked.connect(lambda checked, i=i: self._number(i))
UPDATE: clicked
has a default checked
argument that would override the value of i
, so it must be added to the argument list before the keyword value.
一个更具可读性、更少魔力的替代方案是functools.partial
:
self._numberButtons[i].clicked.connect(partial(self._number, i))
我在这里使用新型信号和槽语法只是为了方便,旧式语法的工作原理是一样的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)