Petter
Petter

Reputation: 38654

PySide: multiple decorators for widget slots

My main window class in Python with PySide has lots of member functions like:

@QtCore.Slot()
def on_myButton_clicked(self) :
    ...

I would like to add my own decorator, but the following does not work:'

def my_decorator(f) :
    def wrapper(*args, **kwargs) :
            f(*args, **kwargs)  
    return wrapper

...

@QtCore.Slot()
@my_decorator
def on_myButton_clicked(self) :
    ...

When I do this, QtCore.QMetaObject.connectSlotsByName does not seem to connect the method with the button. Can this be easily fixed?

Upvotes: 1

Views: 507

Answers (1)

Chris Morgan
Chris Morgan

Reputation: 90902

connectSlotsByName works from the registered slots, and Slot works from the __name__ of the function that it is given.

The name of on_myButton_clicked when it is defined is 'on_myButton_clicked'. However, you then pass it through the decorator; the decorator function returns a function named 'wrapper'. So Slot registers it with that name, not 'on_myButton_clicked'.

To solve this, use functools.wraps:

def my_decorator(f):
    @functools.wraps(f)
    def wrapper(*args, **kwargs):
        f(*args, **kwargs)
    return wrapper

This, among other things, sorts out __name__ so that the slot will be registered under the correct name.

It's a good habit to always use functools.wraps; it will make debugging some situations easier.

Upvotes: 5

Related Questions