2013-01-05 17 views
5

Utknąłem z następującym problemem. Próbuję połączyć funkcję lambda z sygnałem, aby ostatecznie przekazać dodatkowe dane.PyQT Łączenie funkcji lambda z Signal

def createTimeComboBox(self,slotCopy): 
    timeComboBox = QComboBox() 

    #... 

    cmd = lambda func=self.test:func() 
    self.connect(timeComboBox, SIGNAL("currentIndexChanged(int)"),cmd) 

#... 

def test(self, value): 
    print value 

Kiedy biegnę createTimeComboBox(), otrzymuję ten błąd:

TypeError: 'int' object is not callable 

Zmiana

self.connect(timeComboBox, SIGNAL("currentIndexChanged(int)"),cmd) 

do

self.connect(timeComboBox, SIGNAL("currentIndexChanged(int)"),self.test) 

działa prawidłowo, ale chciałbym, aby móc przekazać slotCopy zmienna również, więc zakładałem, że muszę użyć podejścia lambda.

Zrobiłem to wcześniej z sygnałem QPushButton 's clicked() i to działało dobrze.

Mam nadzieję, że to ma sens - czy ktoś ma jakieś pomysły? Dzięki za wszelkie sugestie! Cheers Dave

Odpowiedz

5

Twój lambda akceptuje parametr (func):

lambda func=self.test:func() 

Chociaż parametr ma wartość domyślną, zostanie zastąpiony, jeśli parametr zostanie przekazany. Patrząc na sygnał, currentIndexChanged(int), pokazuje, że sygnał przejdzie parametr liczby całkowitej. func będzie liczbą całkowitą pochodzącą z currentIndexChanged. Później robi func() będzie skutecznie próby wywołania obiektu całkowitą co oczywiście nie jest legalne (jako błąd wskazuje)

trzeba innego parametru w swojej lambda „złapać” przekazany parametr bez przesłanianie parametr func:

cmd = lambda value, func=self.test: func(value) 

Nawiasem mówiąc, twoja metoda test oczekuje parametru, więc nie możesz po prostu wykonać func().

Nie masz problemu z sygnałem clicked(), ponieważ nie przekazuje on parametru do zastąpienia wartości domyślnej.

+0

Niesamowite dziękuję, to działało! Dzięki za wyjaśnienie tego! –

+0

Plus od mnie, skąd wiedziałeś, że parametr został nadpisany? – user1767754

+0

@ user1767754 przy okazji sygnały działają w Qt. Sloty mogą mieć te same lub mniej argumentów, a dodatkowe będą ignorowane. Ale pozostałe zostaną przekazane. Nie ma znaczenia, czy masz domyślny argument, czy nie. Jeśli sygnał przejdzie przez argument, slot otrzyma go, jeśli będzie mógł. – Avaris

3

sprawdzić, czy to działa dla Ciebie:

timeComboBox.currentIndexChanged.connect(self.test) 

Oto mały przykład roboczych, demonstrując nowe połączenie sygnałów Styl/slotów zi bez lambdas:

#!/usr/bin/env python 
#-*- coding:utf-8 -*- 

from PyQt4 import QtCore, QtGui 

class myWindow(QtGui.QWidget): 
    def __init__(self, parent=None): 
     super(myWindow, self).__init__(parent) 

     self.comboBox = QtGui.QComboBox(self) 
     self.comboBox.addItems([str(x) for x in range(3)]) 
     self.comboBox.currentIndexChanged.connect(self.on_comboBox_currentIndexChanged) 

     slotLambda = lambda: self.on_comboBox_currentIndexChanged_lambda("some_value") 
     self.comboBox.currentIndexChanged.connect(slotLambda) 

    @QtCore.pyqtSlot(int) 
    def on_comboBox_currentIndexChanged(self, value): 
     print value 

    @QtCore.pyqtSlot(str) 
    def on_comboBox_currentIndexChanged_lambda(self, string): 
     print string 

if __name__ == "__main__": 
    import sys 

    app = QtGui.QApplication(sys.argv) 
    app.setApplicationName('myWindow') 

    main = myWindow() 
    main.show() 

    sys.exit(app.exec_()) 
+0

Hej, dzięki za to! Nie udało mi się jeszcze tego przejrzeć, ale mam nadzieję, że uda się to później. –