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

问题描述 投票:0回答:4

我有一个循环。我创建了一个

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)

注意:我的

connect
函数返回
True

如何在循环中创建

connect
函数来枚举所有
instances

python qt pyqt qt-signals qtcore
4个回答
7
投票

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

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
投票

我有同样的问题,你应该使用

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


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
函数中。我会提供一个清晰的例子,但正如另一个答案所说,您的问题中的格式似乎变得非常混乱,我可能会为您的特定应用程序弄错。如果您没有遵循我所说的,请使问题中的代码更清晰,我将尝试创建一个示例!


0
投票

创建单独的函数“make_callback”并在 for 循环中向其传递参数的示例。这解决了只有最后一个 lambda 函数连接到实例的问题。

for button_widget, button_dict in zip(self.button_widget_dictionary.values(),
                                                  self.button_page_dictionary.values()):
                button_widget.pressed.connect(self.make_callback(button_dict))


def make_callback(self,button_dict):

        return lambda: self.central_widget.add_graph_tab_dict(
            button_dict['Tab_options']['name'][0] + ': ' 
          + button_dict['Tab_options']["graph_title"][0:4] + "...",
            button_dict)

© www.soinside.com 2019 - 2024. All rights reserved.