从ANY小部件获取鼠标按下事件



我有一个QMainWindow应用程序,里面有多个小部件(按钮、标签等(。

当用户按下应用程序的任意位置时,我如何获取事件?

我尝试自定义mousePressEvent()功能,但当按下其他小部件(按钮、标签等(时,这不接受事件。

说明:

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

工具:

另一方面,通常有几种方法可以侦听事件,例如:

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

  • 使用事件筛选器。

解决方案:

另一种选择是将以前的一些方法应用于所有小部件,但您可以为当前目标放弃所有这些方法,例如:

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

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

有了以上内容,问题会在小部件方面受到攻击,但还有其他选择:

  • 覆盖Q{Core, GUi,}Applicationnotify()方法,验证它是一个小部件,并且它属于窗口,这也意味着区分事件是否已经被使用。

  • 收听与窗口相关的鼠标事件(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)

最新更新