pyqt事件机制
一、什么是pyqt事件机制?
事件是指用户操作或系统发生的各种动作,比如鼠标点击、键盘输入、窗口大小变化等。事件可以由用户或操作系统触发,然后被传递给应用程序进行处理。PyQt的事件机制通过事件循环(Event Loop)和事件过滤器(Event Filter)来实现。
事件循环是PyQt应用程序的核心机制,它负责接收事件、分发事件和调用对应的事件处理函数。事件循环不断地从操作系统接收事件,并将它们分发给应用程序的对象。每个对象都可以通过重写对应的事件处理函数来响应不同类型的事件。
事件过滤器允许应用程序在事件到达目标对象之前对事件进行拦截和处理。通过设置事件过滤器,应用程序可以截获事件并在处理前进行一些操作,比如修改事件的属性、过滤掉不需要的事件等。
总之,信号与槽机制是对事件机制的高级封装,事件机制更偏向于底层。
二、图解事件机制的流程
注:由于是浅析,不对事件过滤做过多描述,会在后续再进行详细研究。
1、循环检查消息队列
- 不断的按顺序检测消息队列中是否有消息
- 如果发现”事件消息”,则会包装成“QEvent 对象”进行分发处理
2、单次循环流程
三、利用代码简单演示事件机制流程
1、基础代码
import sys
from PyQt5.Qt import *app = QApplication(sys.argv)window = QWidget()btn = QPushButton(window)
btn.setText("自定义按钮")
btn.move(100, 100)def onPressed():print("按钮被点击了")btn.pressed.connect(onPressed)window.show()sys.exit(app.exec_())
程序实现的基本功能:自定义一个按钮,点击后在控制台打印信息。如下为演示图:
2、重写QApplication的notify方法
-
修改的代码:
import sys from PyQt5.Qt import *# 添加自定义类,继承QAoolication,重写notify方法 class MyApp(QApplication):def notify(self, receiver, evt) -> bool:# 由于事件比较多,需要过滤一些事件if receiver.inherits("QPushButton") and evt.type() == QEvent.MouseButtonPress:print("1. 鼠标被按下了,evt:", evt)return super(MyApp, self).notify(receiver, evt)app = MyApp(sys.argv)#修改为自己的类window = QWidget()btn = QPushButton(window) btn.setText("自定义按钮") btn.move(100, 100)def onPressed():print("按钮被点击了")btn.pressed.connect(onPressed)window.show()sys.exit(app.exec_())
-
演示图:
3、重写QPushButton的event方法
-
修改的代码:
import sys from PyQt5.Qt import *class App(QApplication):def notify(self, recevier, evt):if recevier.inherits("QPushButton") and evt.type() == QEvent.MouseButtonPress:print(recevier, evt)return super().notify(recevier, evt)class Btn(QPushButton):def event(self, evt):if evt.type() == QEvent.MouseButtonPress:print(evt)return super().event(evt)def mousePressEvent(self, *args, **kwargs):print("鼠标被按下了......")# return super().mousePressEvent(*args, **kwargs)app = App(sys.argv)window = QWidget()btn = Btn(window) btn.setText("按钮") btn.move(100, 100)def cao():print("按钮被点击了")btn.pressed.connect(cao)window.show()sys.exit(app.exec_())
-
演示图:
4、重写QPushButton的mousePressEvent方法
-
修改的代码:
import sys from PyQt5.Qt import *# 添加自定义类,继承QAoolication,重写notify方法 class MyApp(QApplication):def notify(self, receiver, evt) -> bool:# 由于事件比较多,需要过滤一些事件if receiver.inherits("QPushButton") and evt.type() == QEvent.MouseButtonPress:print("1. 鼠标被按下了,evt:", evt)return super(MyApp, self).notify(receiver, evt)# 添加自定义按钮类,继承QPushButton,重写event方法 class MyBtn(QPushButton):def event(self, event) -> bool:if event.type() == QEvent.MouseButtonPress:print("2. 鼠标被按下了,evt:", event)return super(MyBtn, self).event(event)#重写mousePressEvent方法def mousePressEvent(self, event) -> None:print("3. 鼠标被按下了,evt:", event)return super(MyBtn, self).mousePressEvent(event)app = MyApp(sys.argv)#修改为自己的类window = QWidget()btn = MyBtn(window)#修改为自己的类 btn.setText("自定义按钮") btn.move(100, 100)def onPressed():print("按钮被点击了")btn.pressed.connect(onPressed)window.show()sys.exit(app.exec_())
-
演示图:
四、总结
根据我的理解,pyqt的事件机制主要分为下面过程:
1. 事件进入消息队列,循环中处理每次循环收集到的事件;2. 事件传递:* 顶端的QApplication用notify接收事件,并区分控件类型,分发给正确的控件(receiver);* receiver接收到事件后由event方法进行二次分发,传递给正确的处理方法(如本例的mousePressEvent方法);* 若绑定了信号与槽,对应的处理方法继续传递,发送信号,调用对应的槽函数。