2013-01-05 14 views
5

Sono bloccato con il seguente problema. Sto provando a collegare una funzione lambda a un segnale per passare alcuni dati extra alla fine.PyQT Collegamento della funzione lambda al segnale

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 

Quando eseguo createTimeComboBox(), ottengo questo errore:

TypeError: 'int' object is not callable 

Modifica

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

a

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

funziona bene, ma vorrei essere in grado di passare il slotCopy variabile, quindi presume che ho bisogno di utilizzare l'approccio lambda.

L'ho fatto precedentemente con un segnale QPushButtonclicked() e ha funzionato correttamente.

def createToDoctorButton(self,extraData): 
    toDoctorButton = QPushButton() 

    cmd = lambda func=self.goToDoctor:func(extraData) 
    self.connect(toDoctorButton, SIGNAL('clicked()'),cmd) 

    return toDoctorButton 

def goToDoctor(self,extraData): 
    print extraData 

Spero che abbia senso: qualcuno ha qualche idea? Grazie per eventuali suggerimenti! Acclamazioni Dave

risposta

5

tuo lambda accetta un parametro (func):

lambda func=self.test:func() 

Sebbene il parametro abbia un valore predefinito, verrà sostituito se viene passato un parametro. Guardando il segnale, currentIndexChanged(int), viene mostrato che il segnale passerà un parametro intero. func sarà il numero intero che viene da currentIndexChanged. Più tardi, facendo func() sarà effettivamente cercando di chiamare un oggetto intero che, ovviamente, non è legale (come l'errore indica)

È necessario un altro parametro nel vostro lambda al parametro passato "catturare" senza sostituire il parametro func:

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

A proposito, il tuo metodo test si aspetta un parametro, quindi non puoi fare solo func().

Non hai avuto questo problema con il segnale clicked() perché non passa un parametro per sostituire il valore predefinito.

+0

Fantastico grazie, ha funzionato a meraviglia! Grazie per averlo spiegato! –

+0

Oltre a me, come facevi a sapere che il parametro è stato sovrascritto? – user1767754

+0

@ user1767754 a proposito dei segnali funzionano in Qt. Gli slot possono avere argomenti uguali o minori e quelli extra verranno ignorati. Ma i restanti saranno passati. Non importa se hai un default per quell'argomento o no. Se un segnale passa un argomento, lo slot lo riceverà se possibile. – Avaris

3

vedere se questo funziona per voi:

timeComboBox.currentIndexChanged.connect(self.test) 

Ecco un piccolo esempio di lavoro, dimostrando nuova connessione segnali di stile/slot con e senza lambda:

#!/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

Ehi, grazie per questo! Non sono ancora riuscito a farcela, ma ci penserò più tardi oggi, si spera! –

Problemi correlati