QtCore.QObject.connect in a loop only affects the last instance

耗尽温柔 提交于 2019-11-26 15:33:16

I have same problem , you should use functools.partial such as:

for key, val in a_DICT_THAT_YOU_STORED_YOUR_OBJECTS_AND_STRINGS:
    obj = partial(   findInstance.projectsInstance.myslot,arg1="TWCH",arg2=self,arg3=key,arg4=val.checkState() )
    QtCore.QObject.connect(val, QtCore.SIGNAL(_fromUtf8("stateChanged (int)")), obj)

Of course, argX should set to your real name of your argument of your function name.

Put the loop variable in a default argument, like this:

lambda state, instance=instance: findInstance.projectsInstance.myslot(
    "TWCH", findInstance, instance.text(), instance.checkState(), instance)

This will give each lambda its own local copy of the instance variable.

EDIT

Here's a simple script that demonstrates how to use default lambda arguments:

from PyQt4 import QtGui

class Window(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        layout = QtGui.QVBoxLayout(self)
        for index in range(4):
            instance = QtGui.QCheckBox('Checkbox(%d)' % index, self)
            instance.stateChanged.connect(
                lambda state, instance=instance:
                    self.mySlot(instance.text()))
            layout.addWidget(instance)

    def mySlot(self, text):
        print('clicked: %s' % text)


if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())

The problem is that you are creating a function using lambda where some of the variables inside the function are not being passed in as arguments to the function. When the lambda function is executed, when the signal is emitted, it uses the value of those variables (like instance) at that moment in time. To be clear, every lambda function you make is using the value of instance at runtime, rather than define time. So instance only holds a reference to the object used in the last iteration of our loop, which explains the behaviour you are seeing.

Some useful information can be found here (read the comments too) http://eli.thegreenplace.net/2011/04/25/passing-extra-arguments-to-pyqt-slot/

From the comments of the above link:

What you can do is have another function generate the lambda, i.e. something like:

def make_callback(param):   
        return lambda: self.on_button(param)

And in the connection, call make_callback(i). Then a different lambda is created for each iteration.

So you would want to generalise this and pass in things like instance to the make_callback function and then place your lambda definition inside the make_callback function. I would provide a clear example of this, but as the other answer says, your formatting appears to have become very messed up in your question and I would likely get it wrong for your specific application. If you aren't following what I've said, make the code in your question clearer and I'll have a go at creating an example!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!