【问题标题】:Get mouse press event from ANY widget从任何小部件获取鼠标按下事件
【发布时间】:2021-08-11 22:56:50
【问题描述】:

我有一个 QMainWindow 应用程序,其中包含多个小部件(按钮、标签等)。

当用户按下应用程序的 ANYWHERE 时如何获取事件?

我尝试自定义mousePressEvent() 函数,但是当其他小部件(按钮、标签等)被按下时,它不接受该事件。

【问题讨论】:

  • 你可以使用eventFilter

标签: python pyqt pyside2


【解决方案1】:

解释:

小部件之间鼠标事件的处理是从子级到父级的,也就是说,如果子级不接受事件(它不使用它),那么它会将事件传递给父级。例如,如果您按下 QPushButton,它会接受事件并且不会通知父级,这与不使用它的 QLabel 不同,因此事件会传递给父级。

工具:

另一方面,一般有几种方法可以监听事件,例如:

  • 覆盖任何方法,如 mousePressEvent、keyPressEvent 等或 event 或 customEvent 方法。

  • 使用事件过滤器。

解决办法:

另一种方法是将某些先前的方法应用于所有小部件,但您可以将它们全部丢弃以用于当前目标,例如:

  • 在第一种和第二种方法中,它将涉及检测何时添加或删除小部件(使用QEvent::ChildAddedQEvent::ChildRemoved)。

  • 在第一种方法中,它意味着多次覆盖不可能的方法。

有了上面,问题是在小部件端攻击,但还有其他替代方案:

  • 重写Q{Core, GUi,}Applicationnotify()方法,验证它是一个widget并且属于window,这也意味着判断事件是否已经被消费。

  • 监听与窗口(QWindow)相关的鼠标事件。

在这种情况下最合理的是第二种方法。

import sys

from PyQt5 import QtCore, QtWidgets


class MouseObserver(QtCore.QObject):
    pressed = QtCore.pyqtSignal(QtCore.QPoint)
    released = QtCore.pyqtSignal(QtCore.QPoint)
    moved = QtCore.pyqtSignal(QtCore.QPoint)

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

        self.window.installEventFilter(self)

    @property
    def window(self):
        return self._window

    def eventFilter(self, obj, event):
        if self.window is obj:
            if event.type() == QtCore.QEvent.MouseButtonPress:
                self.pressed.emit(event.pos())
            elif event.type() == QtCore.QEvent.MouseMove:
                self.moved.emit(event.pos())
            elif event.type() == QtCore.QEvent.MouseButtonRelease:
                self.released.emit(event.pos())
        return super().eventFilter(obj, event)


class MainWindow(QtWidgets.QMainWindow):
    pass


def main(args):
    app = QtWidgets.QApplication(args)

    w = MainWindow()
    w.show()

    mouse_observer = MouseObserver(w.window().windowHandle())
    mouse_observer.pressed.connect(lambda pos: print(f"pressed: {pos}"))
    mouse_observer.released.connect(lambda pos: print(f"released: {pos}"))
    mouse_observer.moved.connect(lambda pos: print(f"moved: {pos}"))

    app.exec_()


if __name__ == "__main__":
    main(sys.argv)

【讨论】:

  • 太棒了!像魅力一样工作!
猜你喜欢
  • 2011-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-16
  • 1970-01-01
  • 1970-01-01
  • 2021-10-05
相关资源
最近更新 更多