Автоматические слоты PyQt: не вызываются при оформлении оберткой

У меня есть QWidget, созданный с помощью Qt Designer, который имеет QPushButton с именем foo, а QWidget имеет метод с именем on_foo_clicked:

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

Во-первых, on_foo_clicked вызывается только в том случае, если он украшен pyqtSlot(). Если я удалю этот декоратор, мне придется вручную подключить self.ui.foo (типа QPushButton) к self.on_foo_clicked в инициализаторе MyWidget, но я не смог найти никакой документации по этому поводу.

Во-вторых, если я хочу использовать свой собственный декоратор следующим образом:

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

...

@auto_slot
def on_foo_clicked(self):
    pass

это больше не работает. Но работает следующее:

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

Таким образом, проблема заключается не в замене pyqtSlot другим декоратором, а в том, что по какой-то причине функция wrapper вызывает сбой механизма автоматического подключения. Обратите внимание, что описанная выше проблема касается только автоматических подключений; если я добавлю строку в MyWidget.__init__, чтобы явно связать кнопку self.ui.foo с self.on_foo_clicked, тогда декоратор auto_slot с wrapper будет работать, как и ожидалось, и метод будет вызываться при нажатии кнопки.

Есть идеи, что я могу сделать для auto_slot с wrapper, чтобы он работал даже с автоматически подключаемыми слотами?

Причина, по которой я хочу этого, заключается в том, что оболочка может перехватывать исключение, вызванное слотом (указание на ошибку), и выводить на консоль.


person Oliver    schedule 25.02.2015    source источник


Ответы (1)


Мне только что пришло в голову, что проблема в том, что функция wrapper не имеет правильного имени, которое может быть найдено системой автоматического подключения. Таким образом, следующее устраняет проблему:

from functools import wraps
def auto_slot(func):
    @wraps(func)
    def wrapper(self):
        func(self)
    return pyqtSlot()(wrapper)
person Oliver    schedule 25.02.2015