Señales y slots de PyQt4

Estoy escribiendo mi primera aplicación de Python con PyQt4. Tengo una clase MainWindow y una Dialog, que es parte de la clase MainWindow:

self.loginDialog = LoginDialog(); 

Uso slots y señales. Aquí hay una conexión hecha en MainWindow:

 QtCore.QObject.connect(self.loginDialog, QtCore.SIGNAL("aa(str)"), self.login) 

Y trato de emitir señal dentro de la clase Dialog (estoy seguro de que se emite):

 self.emit(QtCore.SIGNAL("aa"), "jacek") 

Lamentablemente, la ranura no se invoca. Intenté sin argumentos también, diferentes estilos de señal de emisión. No hay errores, no hay advertencias en el código. ¿Cuál podría ser el problema?

No se utiliza la misma señal, al emitir y conectar.

QtCore.SIGNAL("aa(str)") no es lo mismo que QtCore.SIGNAL("aa") . Las señales deben tener la misma firma. Por cierto, si está definiendo sus propias señales, no defina parámetros. Simplemente escriba SIGNAL (‘aa’), porque la definición de parámetros es una cosa de C ++ y la versión Python de Qt no necesita esto.

Entonces debería verse así:

 QtCore.QObject.connect(self.loginDialog, QtCore.SIGNAL("aa"), self.login) 

y si pasa cualquier parámetro en emisión, su método de inicio de sesión debe aceptar esos parámetros. Compruebe, si esto ayuda 🙂

Hay algunos conceptos para aclarar.

[Señal QT y ranura] VS [Señal y ranura Python]

Todas las señales y ranuras predefinidas proporcionadas por pyqt se implementan mediante el código c ++ de QT. Cuando quiera tener una señal y ranura personalizadas en Python, es una señal y ranura de Python. Por lo tanto, hay cuatro casos para emitir una señal a una ranura:

  • de una señal QT a una ranura QT
  • de una señal QT a una ranura de Python
  • De una señal de Python a una ranura QT
  • de una señal de Python a una ranura de Python

El siguiente código muestra cómo conectarse para estos cuatro scnarios diferentes

  import sys from PyQt4.QtCore import * from PyQt4.QtGui import * class Foo(QtCore.QObject): def __init__(self, parent=None): super(Foo, self).__init__(parent) dial = QDial() self.spinbox = QSpinbox() # -------------------------------------- # QT signal & QT slot # -------------------------------------- # option 1: more efficient self.connect(self.spinbox, SIGNAL("valueChanged(int)"), dial, SLOT("setValue(int)")) # option 2: self.connect(self.spinbox, SIGNAL("valueChanged(int)"), dial.setValue) # -------------------------------------- # QT signal & Python slot # -------------------------------------- self.connect(self.spinbox, SIGNAL("valueChanged(int)"), self.myValChanged) # -------------------------------------- # Python signal & Qt slot # -------------------------------------- # connect option 1: more efficient self.connect(self, SIGNAL("mysignal"), dial, SLOT("setValue(int)")) # connect option 2: self.connect(self, SIGNAL("mysignal"), dial.setValue) # emit param = 100 self.emit(SIGNAL("mysignal"), param) # -------------------------------------- # Python signal & Python slot # -------------------------------------- # connect self.connect(self, SIGNAL("mysignal"), self.myValChanged) # emit param = 100 self.emit(SIGNAL("mysignal"), param) def myValChanged(self): print "New spin val entered {0}".format(self.spinbox.value()) 

La conclusión es –

La firma de señal para la señal de Python se diferencia de la de la señal QT en que no tiene paréntesis y se puede pasar cualquier tipo de datos de Python cuando se emite. La señal de Python se crea cuando la emites.

Para slot, hay tres formas de firmas.

  • s.connect (w, SIGNAL (“signalSignature”), functionName)
  • s.connect (w, SIGNAL (“signalSignature”), instance.methodName)
  • s.connect (w, SIGNAL (“signalSignature”), instancia, SLOT (“slotSignature”))

Los números 1 y 2 están disponibles para la ranura Python, mientras que los números 2 y 3 están disponibles para la ranura QT. Está claro que, además de la ranura predefinida de QT, cualquier función / método que se pueda llamar a Python se considera como una ranura de Python.

Estos puntos se mencionan en el artículo de Summerfield sobre Señales y ranuras .

[Señal y ranura qt de estilo antiguo] VS [nueva clase y ranura qt de estilo]

Bueno, toda la descripción anterior se basa en la señal y ranura pyqt de estilo antiguo. Como @Idan K sugirió, hay un nuevo estilo alternativo para hacer las cosas, especialmente para la señal Python. Consulte aquí para más.

Revisé tu código y parece que el problema está en la forma en que conectas tu señal

  1. se emite la señal en la clase Ui_Dialog

    self.emit (QtCore.SIGNAL (“aa ()”))

  2. te conectas a la señal en el método setupUi de Ui_MainWindow llamando

    QtCore.QObject.connect (self.loginDialog.ui, QtCore.SIGNAL (“aa ()”), self.login)

observe que el primer parámetro se cambia a self.loginDialog.ui ; su llamada de conexión original estaba usando self.loginDialog, que es del tipo LoginDialog, mientras que la señal es emitida por la clase Ui_Dialog que es propiedad de ui del LoginDialog. Después de este cambio, se llamó al método de inicio de sesión de Ui_MainWindow

Espero que esto ayude, saludos.

Lo que sugirió @bialix debería haber funcionado, pero intente una forma alternativa de conexión:

 class Foo(QtCore.QObject): mysignal = QtCore.pyqtSignal(str, name='mysignal') def connect_to_signal(self): # you can use this syntax instead of the 'old' one self.mysignal.connect(self.myslot) # but this will also work self.connect(self, QtCore.SIGNAL('mysignal(QString)'), self.myslot) self.mysignal.emit("hello") def myslot(self, param): print "received %s" % param 

Para una explicación más detallada de cómo funcionan las señales / ranuras en PyQt, sugiero revisar su documentación, específicamente esta sección .

Como lo señala Gruszczy, debe usar el mismo QtCore.SIGNAL (‘xxx’) para conectar la señal y emitirla. También creo que deberías usar tipos Qt en la lista de argumentos de la función de señal. P.ej:

 QtCore.QObject.connect(self.loginDialog, QtCore.SIGNAL("aa(QString&)"), self.login) 

Y luego emitir con:

 self.emit(QtCore.SIGNAL("aa(QString&)"), "jacek") 

A veces tiene sentido definir la señal solo una vez como variable global y usarla en otro lugar:

 MYSIGNAL = QtCore.SIGNAL("aa(QString&)") ... QtCore.QObject.connect(self.loginDialog, MYSIGNAL, self.login) ... self.emit(MYSIGNAL, "jacek") 

No he usado PyQT4 pero eche un vistazo aquí .

Parece que te perdiste la parte “RANURA” en tu llamada de conexión.

Aquí hay un ejemplo :

 QtCore.QObject.connect(self.loginDialog, QtCore.SIGNAL("NotifyMySignal(int)"), QtCore.SLOT("onNotifyMySignal(int)")); 

entonces

 self.emit(QtCore.SIGNAL('NotifyMySignal(1)')); 

Espero que esto ayude !