PyKDE4: new style signals and slots

Those who use PyQt and PyKDE4 are certainly familiar with the syntax used to connect signals and slots:

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"

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:

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"

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):

# 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)

Signals are emitted with the emit() function and disconnected with the disconnect() function:

# 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()

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:


class MyWidget(QWidget):

    # Signal with no arguments
    operationPerformed = QtCore.pyqtSignal()

    # Signal that takes arguments
    valueChanged = QtCore.pyqtSignal(int)

I merely scratched the surface with this. For more information, check out PyQt’s reference manual, which also covers other cases.

DataMatrix page up

Ok, ok… my definition of “tomorrow” is not like what most people use, apparently. Although I took quite a while, now there is a static page on DataMatrix. There you will find a summary of wht I wrote in my other blog posts regarding this module. Of course, it will be kept up-to-date should I release a new version.

Aside that, I put a contact form on this blog. It may be useful for reports that aren’t directly related to the posts.

DataMatrix 0.5

At last, since it’s been like ages, I decided to put out a new version of DataMatrix. For those who haven’t seen my previous post, DataMatrix is a Pythonic implementation of R’s data.frame. It enables you to manipulate a text file by columns or rows, to your liking, using a dictionary-like syntax.

In this new version there have been a few improvements and correction to a couple bugs (for example saveMatrix did not really save) and the start (only a stub at the moment) of an append function to add more columns (I’ll also think about a function to add rows).

DataMatrix is licensed under the GNU GPL, version 2 only. You can download the installer (Windows) or the source distribution (Linux and other *nixes). The only requirement is Python 2.5 or later installed on your system.

The README currently is a stub, but you can browse the pydoc generated documentation, which details how to instantiate and use DataMatrix objects (or you can turn to my older post).

Also, since git is the new “cool feature of the day”, DataMatrix is is hosted on github’s repository, and you can grab the source with

git clone git://github.com/cswegger/datamatrix.git

Comments and suggestions are welcome. I’ll be putting a static page on DataMatrix tomorrow, if time permits.

data.frames in Python – DataMatrix

For a long time I have tried to handle text files in Python in the same way that R’s data.frame does – that is, direct access to columns and rows of a loaded text file. As I don’t like R at all, I struggled to find a Pythonic equivalent, and since I found none, I decided to eat my own food and write an implementation, which is what you’ll find below.

Continue reading