0

Here is my problem. I want to create n number of QLineEdit widgets (n can be any number, depends on the input values). I can create those QLineEdit widgets, give them object name and text, but I can't define signals on all of them (I want that every QLineEdit widget emits signal when interacting with it). Here is the example od the code:

self.fieldList = {}

for (i, value) in attrMap.iteritems():
    self.fieldList["valueField" + str(i)] = QtGui.QLineEdit()
    self.fieldList["valueField" + str(i)].setObjectName(_fromUtf8("attributeValueField_{0}".format(i)))
    self.fieldList["valueField" + str(i)].setText(_fromUtf8("{0}".format(value.toString())))
    self.fieldList["valueField" + str(i)].cursorPositionChanged.connect(lambda: (self.checkState(self.fieldList["valueField" + str(i)])))

The problem persist in the last line:

self.fieldList["valueField" + str(i)].cursorPositionChanged.connect(lambda: (self.checkState(self.fieldList["valueField" + str(i)])))

I thought that signal would stick to every widget, but because of the loop, signal "jumps" from widget to the widget until it gets to the last widget so only that last widget is able to emit signal. So how can I arrange that every widget emits signal when being changed?

kyuss
  • 15
  • 1
  • 5

2 Answers2

2

Explanation and common solution here (there are many more, just search for e.g. "python lambda loop parameter": https://stackoverflow.com/a/938493

Another common solution is to use a partial function:

import functools
slot = functools.partial( self.checkState, self.fieldList["valueField" + str(i)] )
self.fieldList["valueField" + str(i)].cursorPositionChanged.connect( slot )
Community
  • 1
  • 1
Ingrid
  • 160
  • 3
0

The problem here is the closure, i in your lambda refers to the value i has when the lambda function is called, not when it is defined. So after the loop finished, all is will see the same value.

To fix this:

self.fieldList = {}

for (i, value) in attrMap.iteritems():
    self.fieldList["valueField" + str(i)] = QtGui.QLineEdit()
    self.fieldList["valueField" + str(i)].setObjectName(_fromUtf8("attributeValueField_{0}".format(i)))
    self.fieldList["valueField" + str(i)].setText(_fromUtf8("{0}".format(value.toString())))
    self.fieldList["valueField" + str(i)].cursorPositionChanged.connect(lambda old, new, i=i: (self.checkState(self.fieldList["valueField" + str(i)])))

You can find more about this problem here

Community
  • 1
  • 1
mata
  • 67,110
  • 10
  • 163
  • 162
  • This is it! Thank you so much. I've been struggling with this problem for days! Thanks again! – kyuss Jun 22 '12 at 12:26