在pyqt中以for循环连接多个信号/槽

时间:2017-09-19 12:15:52

标签: python qt pyqt signals-slots

我在PyQt中使用for loop连接多个信号/插槽。代码如下:

# 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点击signalscan_callback slot,然后将字符phase作为参数发送至slotetalonmirrorgain
  • 也是如此

我得到了什么:

  • 由于某些原因,我的函数总是传递字符串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()

3 个答案:

答案 0 :(得分:4)

我在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的值就会存储好。

答案 1 :(得分:2)

你的lambdas在定义时 存储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

扩展示例,作为lambdas不存储button值的证明,请注意,如果button停止存在,则会出错:

del button
for fn in funcs:
  fn()

有输出

funcs.append( lambda : print(button))
NameError: name 'button' is not defined

答案 2 :(得分:0)

如此处所述:Connecting slots and signals in PyQt4 in a loop 使用functools.partial是解决此问题的好方法。

一天来一直在和OP一样的问题上苦苦挣扎。