【问题标题】:Monkey patching QWidget mousePressEvent not triggering QPushButton click猴子修补QWidget mousePressEvent不触发QPushButton点击
【发布时间】:2015-11-20 01:18:43
【问题描述】:

我想检测何时在任何 QWidget 上进行了鼠标单击,因此我尝试像这样对 mousePressEvent 进行猴子修补:

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

它本身可以正常工作,但无法触发 QPushButton 小部件的点击信号。我想我的问题是,程序行为发生任何变化的可能原因是什么?据我所知,我保持相同的签名并调用相同的代码,但有些东西会导致副作用,我不知道是什么。

【问题讨论】:

  • 提供的代码没有提到按钮...您是不是忘记包含某些内容?

标签: python pyqt pyqt5 monkeypatching overriding


【解决方案1】:

QPushButton 类继承 QAbstractButton,而后者又继承 QWidget。如果您对QWidget 类进行猴子补丁,您将为应用程序中的每个小部件覆盖mousePressEvent。这真的是你想做的吗?

之所以没有发出clicked 信号是因为mousePressEvent 是由QAbstractButton 重新实现的,但您的代码从未显式调用它。因此,简单的解决方法是对QAbstractButtonQPushButton 类而不是QWidget 进行猴子补丁。

我不确定为什么覆盖 QWidget.mousePressEvent 会绕过 PyQt 中的子类实现。我猜 Python 的重新实现总是优先于 Qt 的重新实现,尽管这可能意味着事情似乎被称为“乱序”(就继承的逻辑链而言)。

【讨论】:

  • 谢谢,修补 QAbstractButton 就可以了。我仍然很困惑为什么覆盖 QWidget 还不够,但暂时将其视为生活的现实:-/
  • @nqe。我以为我解释得很清楚。你原来的补丁没有调用QAbstractButton.mousePressEvent(它负责发出clicked信号)——它所做的只是调用QWidget.mousePressEvent,实际上什么也没做。
  • 对。我感到困惑的是为什么覆盖QWidget.mousePressEvent 会破坏QAbstractButton.mousePressEvent 的行为?如你所说,后者不称前者,为何这里有因果?实际上在上面的代码中,当我点击QPushButton 时,我得到两个“鼠标按下!”消息,一个用于按钮,一个用于父小部件,但我可以看到在 C++ implementation 中从未调用父级,这也让我感到困惑。
  • @nqe。 Python 端的任何实现都将覆盖(即完全绕过)所有 Qt 实现(无论继承的 logical 顺序是什么)。所以没有任何东西被破坏。事实上,恰恰相反,因为没有别的东西被调用。只有 一个 实现 mousePressEvent 会被调用,除非您自己显式调用基类实现。
  • @nqe。至于你的另一个问题:mousePressEvent 的基类实现将调用event.ignore(),它将事件传播给父级。如果您在补丁底部添加event.accept(),则不会传播该事件。
猜你喜欢
  • 2014-12-02
  • 2012-03-13
  • 2013-12-26
  • 2012-06-14
  • 2012-03-29
  • 2016-10-30
  • 2020-08-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多