Saturday, September 11, 2010

PyQt and Signal overloads

I almost spent half an hour trying to figure out why my code didn't work.

I used a QSignalMapper to connect a couple of clickable widgets to emit just one signal, widgetClicked(int index), instead of having multiple signals, one for each widget. I connected the widgetClicked signal to the mapped signal of the QSignalMapper class and did the required set up for the signal mapper, something like the following snippet:
self._signalMapper = QSignalMapper(self)

for index, widget in enumerate(buttons):
    self._signalMapper.setMapping(widget, index)

Everything worked fine until I changed the signature of widgetClicked to pass a string instead of an int, it didn't work anymore. I only got the following print out: TypeError: connect() failed between 'mapped' and 'widgetClicked' and had no clue why because the mapped signal has a couple of overloads:
void mapped(int i)
void mapped(const QString & text)
void mapped(QWidget * widget)
void mapped(QObject * object)
I did also try changing widgetClicked to not receive any arguments and that worked, which was expected because the receiver is not required to match all arguments of a signal. Of course, it also worked if I changed back to int...

What the #@! is going on? Naturally, I had no option of searching for answers since I was sitting on the train back home from work and had no Internet connection.

Then it come to me, Python is not aware of the C++ signature overload. Python doesn't support overloading. Python/PyQt can't set up the right connection between widgetClicked and mapped. But how do you specify which of the overloads you want to connect to? By indexing:
# This connects your slot/signal to the string-overload
The int overload will be used default by PyQt, that's why my code worked when I connected widgetClicked to mapped w/o specifying which overload I wanted.

No comments:

Post a Comment