在pyqt的for循环中连接倍数signal/slot
Connecting multiples signal/slot in a for loop in pyqt
我在 PyQt 中使用 for loop
连接多个 signal/slots。代码如下:
# Connect Scan Callbacks
for button in ['phase', 'etalon', 'mirror', 'gain']:
getattr(self.ui, '{}_scan_button' .format(button)).clicked.connect(
lambda: self.scan_callback(button))
我的期望:
- 连接按钮
phase_scan_button
单击 signal
到 scan_callback
slot
并将字符串 phase
作为参数发送到 slot
。 etalon
、mirror
和 gain
相同。
我得到的:
- 出于某种原因,我的函数总是传递字符串
gain
作为所有按钮的参数。不确定我是不是很愚蠢(可能)还是一个错误。
供参考,slot
方法:
def scan_callback(self, scan):
print(scan) # Here I always get 'gain'
if self.scanner.isWorking:
self.scanner.isWorking = False
self.scan_thread.terminate()
self.scan_thread.wait()
else:
self.scanner.isWorking = True
self.scan_thread.start()
getattr(self.ui, '{}_scan_button' .format(
scan)).setText('Stop Scan')
getattr(self, '_signal{}Scan' .format(scan)).emit()
你的 lambda 在定义时 不 存储 button
的 值。描述 lambda 函数的代码被解析和编译 ,但在您实际调用 lambda 之前不会执行。
每当单击任何按钮时,都会使用变量当前值 button
。在循环结束时,button
包含 "gain"
,这会导致您看到的行为。
试试这个:
funcs = []
for button in ['phase', 'etalon', 'mirror', 'gain']:
funcs.append( lambda : print(button))
for fn in funcs:
fn()
输出为:
gain
gain
gain
gain
扩展示例,作为 lambda 不存储 button
值的证明,请注意,如果 button
停止存在,您将遇到错误:
del button
for fn in funcs:
fn()
有输出
funcs.append( lambda : print(button))
NameError: name 'button' is not defined
我在 pyqt 中迭代多个小部件的首选方法是将它们作为对象存储在列表中。
myButtons = [self.ui.phase_scan_button, self.ui.etalon_scan_button,
self.ui.mirror_scan_button, self.ui.gain_scan_button]
for button in myButtons:
button.clicked.connect(lambda _, b=button: self.scan_callback(scan=b))
如果您需要单独的字符串 "phase"、"etalon"、"mirror" 和 "gain",您可以将它们存储在另一个列表中,或者创建一个字典,例如
myButtons_dict = {"phase": self.ui.phase_scan_button,
"etalon": self.ui.etalon_scan_button,
"mirror": self.ui.mirror_scan_button,
"gain": self.ui.gain_scan_button}
for button in myButtons_dict:
myButtons_dict[button].clicked.connect(lambda: _, b=button self.scan_callback(scan=b))
请注意,我如何将 lambda 表达式与实体变量一起使用,然后将这些变量传递给函数 self.scan_callback
。这样,button
的值就被永久保存了。
如此处所述:Connecting slots and signals in PyQt4 in a loop
使用 functools.partial
是解决此问题的一个很好的解决方法。
一天以来一直在为与 OP 相同的问题而苦苦挣扎。
我在 PyQt 中使用 for loop
连接多个 signal/slots。代码如下:
# Connect Scan Callbacks
for button in ['phase', 'etalon', 'mirror', 'gain']:
getattr(self.ui, '{}_scan_button' .format(button)).clicked.connect(
lambda: self.scan_callback(button))
我的期望:
- 连接按钮
phase_scan_button
单击signal
到scan_callback
slot
并将字符串phase
作为参数发送到slot
。etalon
、mirror
和gain
相同。
我得到的:
- 出于某种原因,我的函数总是传递字符串
gain
作为所有按钮的参数。不确定我是不是很愚蠢(可能)还是一个错误。
供参考,slot
方法:
def scan_callback(self, scan):
print(scan) # Here I always get 'gain'
if self.scanner.isWorking:
self.scanner.isWorking = False
self.scan_thread.terminate()
self.scan_thread.wait()
else:
self.scanner.isWorking = True
self.scan_thread.start()
getattr(self.ui, '{}_scan_button' .format(
scan)).setText('Stop Scan')
getattr(self, '_signal{}Scan' .format(scan)).emit()
你的 lambda 在定义时 不 存储 button
的 值。描述 lambda 函数的代码被解析和编译 ,但在您实际调用 lambda 之前不会执行。
每当单击任何按钮时,都会使用变量当前值 button
。在循环结束时,button
包含 "gain"
,这会导致您看到的行为。
试试这个:
funcs = []
for button in ['phase', 'etalon', 'mirror', 'gain']:
funcs.append( lambda : print(button))
for fn in funcs:
fn()
输出为:
gain
gain
gain
gain
扩展示例,作为 lambda 不存储 button
值的证明,请注意,如果 button
停止存在,您将遇到错误:
del button
for fn in funcs:
fn()
有输出
funcs.append( lambda : print(button))
NameError: name 'button' is not defined
我在 pyqt 中迭代多个小部件的首选方法是将它们作为对象存储在列表中。
myButtons = [self.ui.phase_scan_button, self.ui.etalon_scan_button,
self.ui.mirror_scan_button, self.ui.gain_scan_button]
for button in myButtons:
button.clicked.connect(lambda _, b=button: self.scan_callback(scan=b))
如果您需要单独的字符串 "phase"、"etalon"、"mirror" 和 "gain",您可以将它们存储在另一个列表中,或者创建一个字典,例如
myButtons_dict = {"phase": self.ui.phase_scan_button,
"etalon": self.ui.etalon_scan_button,
"mirror": self.ui.mirror_scan_button,
"gain": self.ui.gain_scan_button}
for button in myButtons_dict:
myButtons_dict[button].clicked.connect(lambda: _, b=button self.scan_callback(scan=b))
请注意,我如何将 lambda 表达式与实体变量一起使用,然后将这些变量传递给函数 self.scan_callback
。这样,button
的值就被永久保存了。
如此处所述:Connecting slots and signals in PyQt4 in a loop
使用 functools.partial
是解决此问题的一个很好的解决方法。
一天以来一直在为与 OP 相同的问题而苦苦挣扎。