2013-10-22 46 views
1

我有一個循環。我創建了一個QCheckBox並將它放在一個QTableWidget單元格中,並且一切正常。在循環的每一步中,我都稱myslot SLOT爲connect函數,但只應用最後一個QCheckBox實例。我GOOGLE了很多,發現很多人都有我的問題。我已經應用了他們的解決方案,但我的問題依然存在QtCore.QObject.connect循環隻影響最後一個實例

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

回答

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/

從上面的鏈接的評論:

你可以做的是有另一個函數生成的λ,即 例如:

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

而在連接中,請撥打make_callback(i)。然後爲每次迭代創建一個不同的lambda表達式 。

所以,你想推廣這個和事傳似instancemake_callback功能,然後將make_callback函數內部lambda定義。我會提供一個清晰的例子,但正如其他答案所說,你的格式似乎已經變得非常混亂在你的問題中,我可能會錯誤的爲你的具體應用程序。如果你沒有遵循我所說的話,那麼就讓問題中的代碼更清晰,然後我將創建一個示例!

2

把循環變量的默認參數,就像這樣:

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

這將給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_()) 
+0

這是行不通的,因爲信號發射時沒有參數傳遞給插槽。你需要創建一個沒有參數的lambda,但是它仍然有它自己的實例副本。因此,我的答案是你使用一個函數來製作@three_pineapples的lambda –

+0

。它工作得很好:看到我的更新答案爲一個工作示例。正如我在我的原始答案中解釋的那樣,默認參數用於緩存循環變量,因此不需要使用閉包(儘管這也可以)。 – ekhumoro

+0

啊,道歉,我跳過了它的'instance = instance'部分(我剛剛讀了'instance')。你的方法比我的建議更清潔,我將開始在我自己的代碼中使用它 –

相關問題