Thursday, January 14, 2010

New-style PyQt Signals and Slots

I was to lazy to take a look at the new-style signal and slot support which was introduced in PyQt 4.5 until yesterday. I did know that there were something called new-style signals and slots but that was the end of the story. Now I have taken the time and I think it's a cleaner solution than the old-style.

I'll just give you a short intro to whet your appetite, find all details here yourself.
import sys
from PyQt4 import QtCore
from PyQt4 import QtGui

def clicked():
    print "Button Clicked"

qApp = QtGui.QApplication(sys.argv)

button = QtGui.QPushButton("Click Me")
QtCore.QObject.connect(button, QtCore.SIGNAL('clicked()'), clicked)
button.show()

sys.exit(qApp.exec_())
This is the old way of connecting a signal to a slot. To use the new-style support just replace line 11 with following code
button.clicked.connect(clicked)
The new-style support introduces an attribute with the same name as the signal, in this case clicked.

If you need to define your own signal you'll do something like this (off the top of my head):
class X(QtCore.QObject):
    mySignal = QtCore.pyqtSignal(int)

    def emitMySignal(self):
        self.mySignal.emit(100)
And the old way:
class X(QtCore.QObject):
    def emitMySignal(self):
        self.emit(QtCore.SIGNAL('mySignal'), 100)

IMHO the new-style support is more pythonic and you don't have to specify your signals as strings when connecting. If you use pydev (eclipse) you'll also have completion support for signals.

4 comments:

  1. An interesting variation you can use when defining Python slots on the fly
    is to use the signal as a decorator:

    @button.clicked.connect
    def clicked():
        print "Button clicked"

    ReplyDelete
  2. gldnspud: Ah, sweet. Have to try it.

    ReplyDelete
  3. i think the correct function is
    mySignal = QtCore.pyqtSignal(int)

    ReplyDelete
  4. Anonymous you are right, there is mistake. Author of blog should correct it.

    ReplyDelete