Details
-
Bug
-
Resolution: Invalid
-
Not Evaluated
-
None
-
5.15.3, 6.0.3
-
None
Description
In order to be able to pass additional information to the callback, I'm using a lambda function to call the real handler when the signal is triggered.
Doing so works in general, however there is a specific case where this breaks inexplicably: when done in a loop, feeding the lambda a variable that is part of the loop and is out of its scope.
I have built a proof of concept based on the basic tutorial:
import sys from PySide6.QtWidgets import (QLineEdit, QPushButton, QApplication,QRadioButton, QVBoxLayout, QDialog,QMainWindow, QLabel) class Form(QDialog): def set_label(self,t,x): if t: self.lab.setText(x) print(x) def __init__(self, parent=None): super(Form, self).__init__(parent) self.lab = QLabel("ok") self.r1 = QRadioButton("1") self.r2 = QRadioButton("2") layout = QVBoxLayout() layout.addWidget(self.lab) layout.addWidget(self.r1) layout.addWidget(self.r2) self.setLayout(layout) self.set_label(True,'okok') ### This would work #self.r1.toggled.connect(lambda t: self.set_label(t,"1")) #self.r2.toggled.connect(lambda t: self.set_label(t,"2")) for num in [1,2]: if num == 1: x = self.r1 else: x = self.r2 print(num) print(x) x.toggled.connect(lambda toggled: self.set_label(toggled, f"{num}")) # This would work #x.toggled.connect(lambda toggled,num=num: self.set_label(toggled, f"{num}")) if __name__ == '__main__': app = QApplication(sys.argv) form = Form() form.show() sys.exit(app.exec_())
This program should write "1" or "2" on its label, depending on which radio button is checked.
If the connecting loop is replaced by the individual connections, commented above it, it works.
Oddly enough if the variable is passed explicitly and re-scoped (see the comment below, the only difference being "num=num" as an additional lambda parameter) it also works.
I have tried reproducing this behaviour in pure python as such:
F = lambda: None def set_f(f): global F F = f def p(a,b): print(a,b) for x in range(1,4): j = lambda t: p(t,x) set_f(j) F(2)
but this program works as expected, which makes me think that the problem lies somewhere between QT and PySide.
I was able to reproduce this in both PySide2 and PySide6.
I am attaching both my test scripts for convenience.