New-style signal-slot connection mechanism in PyQt
April 24th, 2011 at 6:49 pmIn most of the PyQt code samples you find online and in books (including, I confess, my examples and blog posts) the "old-style" signal-slot connection mechanism is used. For example, here’s a basic push-button window:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class MyForm(QMainWindow):
def __init__(self, parent=None):
super(MyForm, self).__init__(parent)
the_button = QPushButton('Hello')
self.connect(the_button, SIGNAL('clicked()'), self.on_hello)
self.setCentralWidget(the_button)
def on_hello(self):
print('hello!!')
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
form = MyForm()
form.show()
app.exec_()
The relevant code is:
self.connect(the_button, SIGNAL('clicked()'), self.on_hello)
Apart from being verbose and un-Pythonic, this syntax has a serious problem. You must type in the C++ signature of the signal exactly. Otherwise, the signal just won’t fire, without an exception or any warning. This is a very common mistake. If you think that clicked() is a simple enough signature to write, how about these ones (taken from real code):
SIGNAL("currentRowChanged(QModelIndex,QModelIndex)")
SIGNAL('marginClicked(int, int, Qt::KeyboardModifiers)')
The "new-style" signal-slot connection mechanism is much better. Here’s how the button click connection is done:
the_button.clicked.connect(self.on_hello)
This mechanism is supported by PyQt since version 4.5, and provides a safer and much more convenient way to connect signals and slots. Each signal is now an attribute that gets automatically bound once you access it. It has a connect method that simply accepts the slot as a Python callable. No more C++ signatures, yay!
PyQt 4.5 was released almost 2 years ago – it’s time to switch to the new mechanism.
Related posts:

April 24th, 2011 at 20:05
You might also consider switching to PySide, which is essentally compatible with PyQt but is LGPL’d and developed by Nokia.
April 24th, 2011 at 22:32
wow! I’m using PyQt for a while and didn’t knew that!
But how it works when you have both “clicked()” and “clicked(bool)” versions of the slot, like in the QCheckBox object?
April 25th, 2011 at 06:15
df,
I’ve mentioned PySide in the blog in the past. Interestingly, it also has a similar “new-style” connection mechanism.
Franklin,
This is actually covered in the PyQt documentation. Your slot will fire for both signals. If you want more fine-grained control you should use the
@pyqtSlotdecorator.April 25th, 2011 at 06:48
Also it is possible to use Python decorator syntax to make connection between a signal and slot:
For example:
(PyQt versiosn 4.7.4)
The above code snippet connects the
currentIndexChangedsignal (which is emitted when the current index in the ComboBox is changed) with the methodhandle.April 26th, 2011 at 02:39
@Sateesh i didn’t knew that, now the code is more cleaner
May 15th, 2011 at 02:07
Ah, this is good to know. I never knew!
thanks Eli
June 27th, 2011 at 07:45
nice to learn new things, the code is much easier,
March 14th, 2012 at 18:10
self.ui.comboBox.activated.connect(self.pass_Net_Adap)
def pass_Net_Adap(self):
print ” Adap”
print str(self.ui.comboBox.currentText())