Обратный вызов PyQt5 с другим именем, вызываемый на valueChanged - PullRequest
0 голосов
/ 30 августа 2018

Я хочу, чтобы объекту было доступно более одного обратного вызова, но определение any последующего обратного вызова в объекте перезаписывает все предыдущие обратные вызовы. Тем не менее, обратные вызовы оформлены, что, кажется, портит вещи. Как определить обратные вызовы уровня объекта, чтобы в них можно было использовать self?

В следующем примере, который вы можете запустить на любом компьютере с Python 3.x и PyQt5.11.x, спинбокс подключается к двум обратным вызовам valueChanged. Они называются A и C. Однако второй обратный вызов C никогда не срабатывает, а третий обратный вызов D срабатывает вместо этого. D не должен срабатывать.

Обратные вызовы печатают свои буквы и значение spinbox, поэтому ожидаемый результат при вращении spinbox:

got A 1
got C 1

Тем не менее, фактический результат:

got A 1
got D 1

Это неправильно, потому что спинбокс подключен к

callbackA
self.callbackC

Я не знаю, почему вызывается D, поскольку я нигде не упоминаю об этом. Однако, если мы удалим любой из декораторов из C или D, они снова будут работать. Что я делаю не так?

Код, о котором идет речь:

from PyQt5 import QtWidgets
from PyQt5.QtCore import pyqtSlot


def silenceCallbacks(*elements):
    """Silence events for the duration of a callback. Mostly skipped for this reproduction."""
    def silenceCallbacksOf(callback):
        def silencedCallback(self, *args, **kwargs):
            callback(self, *args, **kwargs)
        return silencedCallback
    return silenceCallbacksOf


@pyqtSlot(int)
@silenceCallbacks()
def callbackA(px: int):
    #correctly called
    print('got A', px)

@pyqtSlot(int) #this overwrites the last three functions
@silenceCallbacks()
def callbackB(px: int):
    #correctly not called
    print('got B', px)


class RecordingSettings(QtWidgets.QDialog):
    @pyqtSlot(int)
    @silenceCallbacks()
    def callbackC(self, px: int):
        #incorrectly not called
        print('got C', px)

    @pyqtSlot(int) #this overwrites the previous pyqtSlot-decorated function
    @silenceCallbacks()
    def callbackD(self, px: int):
        #incorrectly called
        print('got D', px)


    def __init__(self, window):
        super().__init__()

        spin = QtWidgets.QSpinBox()

        spin.valueChanged.connect(callbackA)
        spin.valueChanged.connect(self.callbackC)

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(spin)
        self.setLayout(layout)
        self.show()



app = QtWidgets.QApplication([])
recSettingsWindow = RecordingSettings(app)
recSettingsWindow.show()
app.exec_()

1 Ответ

0 голосов
/ 14 сентября 2018

Итак, исправление для этого оказывается простым, если неочевидным. После 10 часов неприятностей:

Ты, блин, изменишься

@pyqtSlot(int)

к черту

@pyqtSlot(int, name="unique_name_here")

и это работает.

Я рекомендую использовать имя функции, оформленной как уникальное имя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...