PyQt: connectant signals amb slots

De Cacauet Wiki
Salta a la navegació Salta a la cerca

En el GUI i en PyQt en particular caldrà que connectem els objectes per tal d'emprendre accions (events) a través dels elements gràfics (normalment el ratolí).

Els elements a connectar son:

  • Signals: events desencadenats per un objecte gràfic, i.e., botó premut, canvi de valor d'un slider, etc.
  • Slots: funcions (predefinides o definides per nosaltres) que rebran la signal. Un cop connectats els dos elements, cada cop que es desencdeni un esdeveniment (per exemple, botó clicat) es cridarà la funció (slot) corresponent.

Referències:


Botons

Els botons són l'exemple més elemental. El seu senyal típic és clicked (sense paràmetres).

Exemple 1: connectem un botó a la sortida de l'aplicació:

qbtn.clicked.connect( QtCore.QCoreApplication.instance().quit )

Exemple 2: connectem un botó a una funció nostra:

class Cosa(QtGui.QWidget):
    def __init__(self):
        super(Cosa,self).__init__()
        self.initUI()
    def initUI()
        ...
        boto = QtGui.QPushButton(self)
        boto.clicked.connect( self.fesAlgunaCosa )
        ...
    def fesAlgunaCosa(self):
        print "hola que tal..."

Com podeu veure, un botó no té cap paràmetre i la funció que ataca tampoc.

Sliders

En aquest exemple de signals i slots en zetcode.com podem veure com connectar un slider i un LCD:

slider.valueChanged.connect( lcd.display )

El què cal tenir en compte és que tant la signal com el slot han de tenir els mateixos paràmetres. Si consultem la documentació veurem que valueChanged emet un "int" com a paràmetre, i el slot display del LCD també:


Creem els nostres propis slots

Ara tindrem un widget amb un slider que no volem simplement que vagi a un LCD, sinó que volem utilitzar el seu valor:

class Cosa(QtGui.QWidget):
    def __init__(self):
        super(Cosa,self).__init__()
        self.initUI()
    def initUI()
        ...
        slider = QtGui.QSlider(self)
        slider.valueChanged.connect( self.fesAlgunaCosa )
        ...
    def fesAlgunaCosa(self, valor):
        print "el valor del slider ara és = " + str(valor)

Com podeu veure, hem de saber (mirant la documentació) que la signal valueChanged del slider porta un "int" (valor del slider) i que el podem captar amb la nostra funció. Però en la connexió no s'ha d'especificar:

slider.valueChanged.connect( self.fesAlgunaCosa )

Aquí no apareix cap paràmetre. I tampoc s'ha de posar cap parèntesi a la funció fesAlgunaCosa ja que això implicaria cridar-la.

Per saber qui ha cridat un slot

Es pot saber qui és l'objecte que crida el slot amb la funció QObject.sender() (ens retorna l'objecte que crida la funció de callback):

    def botoPremut(self):
        boto = self.sender()
        print "boto premut " + boto.text()