Oliver
Oliver

Reputation: 29571

PyQt auto slots: not called when decorated with a wrapper

I have a QWidget created via Qt Designer that has a QPushButton named foo, and the QWidget has a method named on_foo_clicked:

class MyWidget(QWidget):
    def __init__(self):
        ...
    @pyqtSlot()
    def on_foo_clicked(self):
        pass

Firstly, the on_foo_clicked is only called if it is decorated with pyqtSlot(). If I remove that decorator, I have to manually connect the self.ui.foo (of type QPushButton) to self.on_foo_clicked in MyWidget's initializer, yet I could not find any documentation about this.

Secondly, if I want to use my own decorator like this:

def auto_slot(func):
    @pyqtSlot()
    def wrapper(self):
        func(self)
    return wrapper

...

@auto_slot
def on_foo_clicked(self):
    pass

it no longer works. But the following works:

def auto_slot(func):
    return pyqtSlot()(func)

So the issue is not the replacement of pyqtSlot by another decorator, but rather that for some reason the wrapper function causes the auto connection mechanism to fail. Note that the above issue only affects automatic connections; if I add a line in MyWidget.__init__ to explicitely connect the self.ui.foo button to self.on_foo_clicked, then the auto_slot decorator with wrapper works as expected and the method gets called when click button.

Any ideas if there is something I can do to auto_slot with wrapper so that it will work even with automatically connected slots?

The reason I want this is so that the wrapper can trap exception raised by slot (indication of a bug) and print to console.

Upvotes: 1

Views: 160

Answers (1)

Oliver
Oliver

Reputation: 29571

Just occurred to me that the problem is that wrapper function does not have the right name to be found by the auto connection system. So the following fixes the problem:

from functools import wraps
def auto_slot(func):
    @wraps(func)
    def wrapper(self):
        func(self)
    return pyqtSlot()(wrapper)

Upvotes: 1

Related Questions