121 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| ---
 | |
| author: einar
 | |
| comments: true
 | |
| date: 2010-03-06 08:04:48+00:00
 | |
| layout: post
 | |
| slug: pykde4-new-style-signals-and-slots
 | |
| title: 'PyKDE4: new style signals and slots'
 | |
| wordpress_id: 763
 | |
| categories:
 | |
| - KDE
 | |
| - Linux
 | |
| tags:
 | |
| - KDE
 | |
| - programming
 | |
| ---
 | |
| 
 | |
| Those who use PyQt and PyKDE4 are certainly familiar with the syntax used to connect signals and slots:
 | |
| 
 | |
| 
 | |
| 
 | |
| [python]
 | |
| from PyQt4 import QtCore
 | |
| from PyQt4 import QtGui
 | |
| from PyKDE4 import kdeui
 | |
| 
 | |
| class MyGUI(QtGui.QWidget):
 | |
| 
 | |
|     def __init__(self, parent=None):
 | |
|         super(MyGUI, self).__init__(parent)
 | |
|         self.pushbutton = kdeui.KPushButton()
 | |
|         self.pushbutton.setText("Push me!")
 | |
|         
 | |
|         QObject.connect(self.pushbutton, QtCore.SIGNAL("clicked()"), 
 | |
|                                self.button_pushed)
 | |
| 
 | |
|     def button_pushed(self):
 | |
|         print "Button clicked"
 | |
| [/python]
 | |
| 
 | |
| 
 | |
| The main advantage of this syntax is that it's very close to the C++ equivalent, and so you can translate easily from C++ to Python. Unfortunately the advantages of this syntax end here. The disadvantages, at least from a Python coding perspective, outweigh the advantages:
 | |
| 
 | |
|   * It's _extremely_ error-prone: make a typo, and not only your signal won't be connected, but you won't even get a warning, your program will simply do nothing;
 | |
|   * In case you have overloaded signals, you have to type the exact signature, going back to the first problem;
 | |
|   * It's not Pythonic at all.
 | |
| 
 | |
| So, in recent PyQt versions (and thus also in PyKDE4) a _new style_ approach was introduced (although the old style is always present should it be the need to). Using the new style, the signals become a property of the object that emits them. and then you use the connect function of that property. Here's the example using the new style-signals:
 | |
| 
 | |
| 
 | |
| 
 | |
| [python]
 | |
| from PyQt4 import QtCore
 | |
| from PyQt4 import QtGui
 | |
| from PyKDE4 import kdeui
 | |
| 
 | |
| class MyGUI(QtGui.QWidget):
 | |
| 
 | |
|     def __init__(self, parent=None):
 | |
|         super(MyGUI, self).__init__(parent)
 | |
|         self.pushbutton = kdeui.KPushButton()
 | |
|         self.pushbutton.setText("Push me!")
 | |
|         # New style
 | |
|         self.pushbutton.clicked.connect(self.button_pushed)
 | |
| 
 | |
|     def button_pushed(self):
 | |
|         print "Button clicked"
 | |
| [/python]
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| As you can see it's much clearer, and much more Pythonic. Also, typos  **will** trigger an AttributeError, which means you'll be able to track where the problem is.  
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| What about overloaded signals? Normally the first defined is the default, but you can use a dictionary-like syntax to access other overloads (signal names are completely made up here):
 | |
| 
 | |
| 
 | |
| 
 | |
| [python]
 | |
| # One signal is without arguments, the other has a bool
 | |
| 
 | |
| # Signal without arguments
 | |
| self.my_widget.connected.connect(self.handle_errors)
 | |
| # Signal with a book
 | |
| self.my_widget.connected[bool].connect(self.handle_errors)
 | |
| [/python]
 | |
| 
 | |
| Signals are emitted with the emit() function and disconnected with the disconnect() function:
 | |
| 
 | |
| [python]
 | |
| # Emit a signal
 | |
| self.pushbutton.clicked.emit()
 | |
| # Emit a signal with a value (an int)
 | |
| self.my_widget.valueChanged.emit(int)
 | |
| # Disconnect another
 | |
| self.my_tabwidget.currentIndexChanged.disconnect()
 | |
| [/python]
 | |
| 
 | |
| 
 | |
| 
 | |
| To define new signals, you can use the _pyqtSignal_ function, specifying which values will the signal take (if any): just define that as a class constant (like in the example) and then you can access them like the wrapped ones:
 | |
| 
 | |
| 
 | |
| 
 | |
| [python]
 | |
| 
 | |
| class MyWidget(QWidget):
 | |
|     
 | |
|     # Signal with no arguments
 | |
|     operationPerformed = QtCore.pyqtSignal()
 | |
| 
 | |
|     # Signal that takes arguments
 | |
|     valueChanged = QtCore.pyqtSignal(int)
 | |
| [/python]
 | |
| 
 | |
| 
 | |
| 
 | |
| I merely scratched the surface with this. For more information, check out [PyQt's reference manual](http://riverbankcomputing.co.uk/static/Docs/PyQt4/pyqt4ref.html), which also covers other cases.
 |