天天看点

PyQt学习随笔:通过自定义类重写QApplication的notify方法捕获应用的所有消息

PyQt程序通过调用QApplication类的exec_()(sys.exit(app.exec_()) 进入程序主循环,开始处理事件,它从事件队列中获取本地窗口系统事件,将它们转化为 QEvents,然后将转换后的事件发送给 QObjects对象。

在QApplication类中,真正负责事件分发处理的是QApplication类的notify方法(函数),该方法负责向接收者发送事件,返回接收事件对象的处理程序返回的值。请注意,对于发送到任何线程中的任何对象的所有事件,都会调用此方法。

对于某些类型的事件(例如鼠标和键事件),如果接收者对事件不感兴趣(例如,它返回false),则事件将传播到接收者的父级,依此类推,直至顶级对象。

因此从QApplication类派生自定义类并重写notify方法可以截获应用接收到的所有事件。

重写notify的语法:

notify(QObject receiver, QEvent event)

其中:

1、参数receiver表示将事件发送给谁;

2、event就是事件参数,如果不了解请参考《​​PyQt学习随笔:Qt事件类QEvent详解​​》的介绍;

3、返回值为receiver的事件处理方法的返回值,如果返回值是False表示不阻拦事件,将事件信息继续向下传递,如果返回True表示消费了事件。

案例代码:

class App(QApplication):
def notify(self, eventobject: QObject, event: QEvent):
"""
        本次重写notify是为了截获应用的所有事件,并针对鼠标和键盘按下事件输出事件相关的信息
        :param eventobject: 事件接收对象
        :param event: 具体事件
        :return: True表示事件已经处理,False表示没有处理,需要继续往下传递
        """
eventtype = event.type()
flag = False
if eventtype==QEvent.MouseButtonPress or eventtype==QEvent.KeyPress:flag=True
if flag:
print(f"***************in app notify,事件类型值={eventtype},事件接收者:\n{eventobject}")
ret = super().notify(eventobject, event)
if flag:print(f"***************in app notify,事件返回值={ret}")
return ret
      

当点击窗口的一个按钮时,上述代码输出信息如下:

***************in app notify,事件类型值=2,事件接收者:
<PyQt5.QtGui.QWindow object at 0x00000000034CE168>
***************in app notify,事件类型值=2,事件接收者:
<PyQt5.QtWidgets.QPushButton object at 0x00000000034CE288>
***************in app notify,事件返回值=True
***************in app notify,事件返回值=True

      

可以看到,一个按钮鼠标点击事件被传递了两次,首先传递给窗口,然后传递给了按钮。

注意:

继续阅读