Исправление обезьяны QWidget mousePressEvent не запускает щелчок QPushButton

Я хотел бы определить, когда на каком-либо QWidget был сделан щелчок мышью, и поэтому я пробовал обезьяну исправлять mousePressEvent следующим образом:

qwidgetmousepressevent = QtWidgets.QWidget.mousePressEvent
def overwriteQWidgetMousePressEvent(self, event):
    print("mouse press!")
    qwidgetmousepressevent(self, event)
QtWidgets.QWidget.mousePressEvent = overwriteQWidgetMousePressEvent

Который отлично работает сам по себе, но не может вызвать сигнал щелчка виджета QPushButton. Я предполагаю, что мой вопрос в том, каковы возможные причины изменения поведения программы? Насколько я могу судить, я сохраняю ту же подпись и вызываю тот же код, но есть что-то, вызывающее побочный эффект, и я не могу понять, что именно.


person nqe    schedule 26.08.2015    source источник
comment
В предоставленном коде не упоминается кнопка... вы что-то забыли включить?   -  person three_pineapples    schedule 26.08.2015


Ответы (1)


Класс QPushButton наследует QAbstractButton, который, в свою очередь, наследует QWidget. Если вы исправляете класс QWidget, вы переопределяете mousePressEvent для каждого виджета в вашем приложении. Это действительно то, что вы хотите сделать?

Причина, по которой сигнал clicked не испускается, заключается в том, что mousePressEvent переопределяется QAbstractButton, но ваш код никогда не вызывает его явно. Таким образом, простое решение состоит в том, чтобы исправить класс QAbstractButton или QPushButton вместо QWidget.

Я точно не знаю, почему переопределение QWidget.mousePressEvent обходит реализации подкласса в PyQt. Я предполагаю, что повторные реализации Python всегда будут иметь приоритет над Qt, даже если это может означать, что вещи называются «не по порядку» (то есть с точки зрения логической цепочки наследования).

person ekhumoro    schedule 26.08.2015
comment
Спасибо, исправление QAbstractButton делает свою работу. Я все еще не понимаю, почему переопределения QWidget было недостаточно, но на данный момент приму это как реальность жизни :-/ - person nqe; 28.08.2015
comment
@nqe. Я думал, что объяснил это довольно ясно. Ваш исходный патч не вызывает QAbstractButton.mousePressEvent (который отвечает за передачу сигнала clicked) — все, что он делает, это вызывает QWidget.mousePressEvent, который фактически ничего не делает. - person ekhumoro; 28.08.2015
comment
Верно. Что меня смущает, так это то, почему переопределение QWidget.mousePressEvent нарушит поведение QAbstractButton.mousePressEvent? Как вы говорите, второе не вызывает первого, так почему же здесь причина и следствие? На самом деле в приведенном выше коде, когда я нажимаю QPushButton, я получаю два нажатия мыши! сообщения, одно для кнопки и одно для родительского виджета, но я вижу это в реализация C++ родитель никогда не вызывается, что меня тоже сбивает с толку. - person nqe; 28.08.2015
comment
@nqe. Любая реализация на стороне Python переопределит (т.е. полностью обойдет) все реализации Qt (независимо от того, каков логический порядок наследования). Так что ничего в любом случае не сломано. Наоборот, на самом деле, потому что больше ничего не вызывается. Будет вызвана только одна реализация mousePressEvent, если только вы сами явно не вызовете реализацию базового класса. - person ekhumoro; 28.08.2015
comment
@nqe. Что касается вашего другого вопроса: реализация базового класса mousePressEvent вызовет event.ignore(), который распространяет событие на родителя. Если вы добавите event.accept() в конец патча, событие не будет распространяться. - person ekhumoro; 28.08.2015
comment
Любая реализация на стороне Python будет переопределять (т.е. полностью обходить) все Qt (независимо от того, каков логический порядок наследования). Поэтому, если я переопределяю QWidget.mousePressEvent, я обхожу реализацию Qt независимо от попытки сохранить указатель на его оболочку в строку 1 и вызвать ее в строке 4? И это влияет на все связанные mousePressEvent? Кстати, я не претендую на сломанные вещи, просто пытаюсь понять. Я ценю ваши попытки объяснить! - person nqe; 28.08.2015
comment
Кроме того, я вижу, что могу проверить экземпляр self, а затем вызвать соответствующий метод, например: могу использовать это как обходной путь, хотя мне нужно вручную перечислить все экземпляры, которые я хотел бы использовать, но все же лучше, чем их получать. Извините, еще один вопрос. Исправление других методов, таких как init, похоже, работает нормально. Знаете, чем они отличаются от метода событий? - person nqe; 28.08.2015
comment
(1) Как я уже сказал: только одна реализация mousePressEvent будет когда-либо вызываться, если только вы сами явно не вызовете реализацию базового класса (что вы делаете через qwidgetmousepressevent). (2) Методы обработки событий (среди прочего) являются виртуальными, что означает, что Qt может вызывать их внутри. Метод __init__ специфичен для Python. - person ekhumoro; 28.08.2015