循环中的QtCore.QObject.connect仅影响最后一个实例

时间:2013-10-22 06:44:10

标签: c++ qt pyqt qtcore qt-signals

我有一个循环。我创建了一个QCheckBox并将其放在QTableWidget单元格中,一切正常。在循环的每个步骤中,我为myslot SLOT调用了一个connect函数,但只应用了最后一个QCheckBox实例。我google了很多,发现很多人都有我的问题。我已经应用了他们的解决方案,但问题仍然存在。

for row in xrange(len(uniqueFields)):
    instance = QtGui.QCheckBox(uniqueFields[row], findInstance.tableWidget)
    print QtCore.QObject.connect(instance,
        QtCore.SIGNAL(_fromUtf8("stateChanged (int)")),
        lambda: findInstance.projectsInstance.myslot(
                    "TWCH", findInstance, instance.text(),
                    instance.checkState(), instance))
    findInstance.tableWidget.setRowCount(findInstance.tableWidget.rowCount() + 1)
    findInstance.tableWidget.setCellWidget(row, 0, instance)

注意:我的connect函数返回True

如何在枚举所有connect的循环中创建instances函数?

3 个答案:

答案 0 :(得分:4)

将循环变量放在默认参数中,如下所示:

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

这将为每个lambda提供instance变量的本地副本。

修改

这是一个简单的脚本,演示了如何使用默认的lambda参数:

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_())

答案 1 :(得分:1)

我遇到同样的问题,您应该使用functools.partial,例如:

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)

当然,argX应该设置你的函数名参数的真实名称。

答案 2 :(得分:0)

问题是你正在使用lambda创建一个函数,其中函数内的一些变量不作为函数的参数传入。执行lambda函数时,当发出信号时,它会使用那个时刻的变量值(如instance)。要清楚,您所做的每个lambda函数都是在运行时使用instance的值,而不是定义时间。所以instance只保存对我们循环的最后一次迭代中使用的对象的引用,这解释了你所看到的行为。

这里可以找到一些有用的信息(也可以阅读评论)http://eli.thegreenplace.net/2011/04/25/passing-extra-arguments-to-pyqt-slot/

从以上链接的评论:

  

你可以做的是有另一个函数生成lambda,即   类似的东西:

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

在连接中,请致电make_callback(i)。然后是一个不同的lambda   为每次迭代创建。

因此,您需要对此进行概括并将instance之类的内容传递给make_callback函数,然后将lambda定义放在make_callback函数中。我会提供一个明确的例子,但正如另一个答案所说,你的格式似乎在你的问题中变得非常混乱,我可能会因你的具体应用而弄错。如果你没有按照我的说法进行操作,那么让你的问题中的代码更清晰,我将会创建一个例子!