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

C++ 循环中的QtCore.QObject.connect仅影响最后一个实例,c++,qt,pyqt,qtcore,qt-signals,C++,Qt,Pyqt,Qtcore,Qt Signals,我有一个线圈。我创建了一个QCheckBox并将其放入QTableWidget单元格中,一切正常。在循环的每个步骤中,我都为myslot SLOT调用了一个connect函数,但只应用了最后一个QCheckBox实例。我在谷歌上搜索了很多,发现很多人都有我的问题。我已经应用了他们的解决方案,但我的问题仍然存在 for row in xrange(len(uniqueFields)): instance = QtGui.QCheckBox(uniqueFields[row], findIn

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

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)
注意:my
connect
函数返回
True


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

问题在于,您正在使用
lambda
创建函数,函数中的一些变量没有作为参数传递给函数。当执行lambda函数时,当发出信号时,它使用这些变量的值(如
实例
)。需要明确的是,您创建的每个lambda函数在运行时都使用
instance
的值,而不是定义时间。因此,
instance
只包含对循环最后一次迭代中使用的对象的引用,这解释了您看到的行为

可以在这里找到一些有用的信息(也请阅读评论)

从上述链接的评论中:

你可以做的是让另一个函数生成lambda,即。 比如:

def make_callback(param):   
        return lambda: self.on_button(param)
在连接中,调用
make\u callback(i)
。然后是另一个lambda 为每个迭代创建


因此,您需要对其进行推广,并将
实例
之类的内容传递给
make_callback
函数,然后将
lambda
定义放在
make_callback
函数中。我会提供一个明确的例子,但正如另一个答案所说,您的格式在您的问题中似乎变得非常混乱,我可能会在您的特定应用程序中出错。如果你没有按照我说的去做,请把问题中的代码弄清楚,我会尝试创建一个例子

问题在于,您正在使用
lambda
创建一个函数,其中函数中的一些变量没有作为参数传递给函数。当执行lambda函数时,当发出信号时,它使用这些变量的值(如
实例
)。需要明确的是,您创建的每个lambda函数在运行时都使用
instance
的值,而不是定义时间。因此,
instance
只包含对循环最后一次迭代中使用的对象的引用,这解释了您看到的行为

可以在这里找到一些有用的信息(也请阅读评论)

从上述链接的评论中:

你可以做的是让另一个函数生成lambda,即。 比如:

def make_callback(param):   
        return lambda: self.on_button(param)
在连接中,调用
make\u callback(i)
。然后是另一个lambda 为每个迭代创建


因此,您需要对其进行推广,并将
实例
之类的内容传递给
make_callback
函数,然后将
lambda
定义放在
make_callback
函数中。我会提供一个明确的例子,但正如另一个答案所说,您的格式在您的问题中似乎变得非常混乱,我可能会在您的特定应用程序中出错。如果你没有按照我说的去做,请把问题中的代码弄清楚,我会尝试创建一个例子

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

lambda state, instance=instance: findInstance.projectsInstance.myslot(
    "TWCH", findInstance, instance.text(), instance.checkState(), instance)
这将为每个
lambda
提供其自身的
实例
变量的本地副本

编辑

下面是一个演示如何使用默认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_())

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

lambda state, instance=instance: findInstance.projectsInstance.myslot(
    "TWCH", findInstance, instance.text(), instance.checkState(), instance)
这将为每个
lambda
提供其自身的
实例
变量的本地副本

编辑

下面是一个演示如何使用默认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_())

我也有同样的问题,你应该使用
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应该设置为函数名参数的实名。

我也有同样的问题,你应该使用
functools。部分
例如:

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应该设置为函数名参数的实名。

这不起作用,因为在发出信号时没有参数传递到插槽。您需要创建一个没有参数的lambda,但它仍然有自己的实例副本。因此,我的答案是,使用函数lambda@three_pineapples. 它工作得非常好:请参阅我的更新答案以了解一个工作示例。正如我在最初的回答中所解释的,默认参数用于缓存循环变量,因此不需要使用闭包(尽管也可以)。啊,抱歉,我跳过了
instance=instance
部分(我刚刚读了
instance
)。你的方法比我的建议干净得多,我将在我自己的代码中开始使用它,但它不起作用,因为在发出信号时没有参数传递到插槽。您需要创建一个没有参数的lambda,但它仍然有自己的实例副本。因此,我的答案是,使用函数lambda@three_pineapples. 它工作得非常好:请参阅我的更新答案以了解一个工作示例。正如我在最初的回答中所解释的,默认参数用于缓存循环变量,因此不需要使用闭包(尽管也可以)。啊,抱歉,我跳过了
instance=instance
部分(我刚刚读了
instance
)。你的方法比我的建议干净得多,我将开始在我自己的代码中使用它