Event problem on Dynamically created combo box in tablewidget
Hi,
I have a QTableWidget, in which I create dynamically some QComboBox. I simplified the code so things might be missing but the important part is in there, it looks like this :
Code:
def testPrint(self, index):
print index
def itemComboBox(self, array, curIndex):
comboBox.addItems(array)
comboBox.setCurrentIndex(curIndex)
return comboBox
def createTable(self):
tw = self.ui.tableWidget
version = [ 'v01', 'v02', 'v03' ]
cb = []
for i range(0,len(version)):
cb.append(self.itemComboBox(version,'v01'))
tw.setCellWidget(i, 0, cb[i])
So no problem with that, it creates what I need to see and when I go through each rows I get the values I want. However, I'm trying to run a function when the comboBox value get changed. I first tried that :
Code:
def createTable(self):
tw = self.ui.tableWidget
version = [ 'v01', 'v02', 'v03' ]
cb = []
for i range(0,len(version)):
cb.append(self.itemComboBox(version,'v01'))
cb[i].currentIndexChanged.connect( lambda: self.testPrint(i) ) ###LINE###
tw.setCellWidget(i, 0, cb[i])
But with this, for some reason, each combobox returns the value from the last in the list, seems like I keep overriding the event in the loop but I don't see how since I use a list with index. So as a test I quickly tried something simple outside of the loop after getting rid of the line ###LINE###
Code:
for k in range(0,len(version)) :
cb[k].currentIndexChanged.connect( lambda: self.testPrint(k) )
Which still doesn't work, then because I was really suspicious I tried that instead:
Code:
cb[0].currentIndexChanged.connect( lambda: self.testPrint(0) )
cb[1].currentIndexChanged.connect( lambda: self.testPrint(1) )
cb[2].currentIndexChanged.connect( lambda: self.testPrint(2) )
And that works ! I really don't get why going through a loop would not work the same way.
Anyone can save me on this one ?
Cheers
Chris
Re: Event problem on Dynamically created combo box in tablewidget
This problem is not related to Qt, but to the way Python captures variables in a closure. Your lambda refers to the variable i defined in the enclosing loop, and Python's semantics bind it to the variable's name and scope, not to its value at the time the closure is created. In other words, i is evaluated when the lambda is executed, not when it is constructed, therefore all lambdas see the last value of i.
I found a Stack Overflow discussion with possible solutions:
http://stackoverflow.com/questions/2...ture-in-python
By contrast, C++ lets you choose how variables are captured, just like ordinary function parameters (by value or reference).
Re: Event problem on Dynamically created combo box in tablewidget
Thanks !
Reading this made me understood the issue and I actually sorted it out pretty simply :
Code:
def testPrint(self, index):
print index
def itemComboBox(self, array, curIndex, ID):
comboBox.addItems(array)
comboBox.setCurrentIndex(curIndex)
comboBox.currentIndexChanged.connect( lambda: self.testPrint(ID) )
return comboBox
def createTable(self):
tw = self.ui.tableWidget
version = [ 'v01', 'v02', 'v03' ]
for i range(0,len(version)):
cb = self.itemComboBox(version,'v01',i)
tw.setCellWidget(i, 0, cb)
By passing the i variable when creating the combo box and creating the event in itemComboBox function itself it sorts out the problem.
Thanks again :D
Chris