1、创建应用程序
from PyQt5.Qt import *
import sys
class Window(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("")
if __name__=="__main__":
# 创建app对象
app = QApplication(sys.argv)
window = QWidget()
btn = QPushButton(window)
btn.setText("按钮")
btn.move(100, 100)
def cao():
print("按钮被点击了")
# 鼠标点下去就触发
btn.pressed.connect(cao)
window.show()
# 创建退出方法,
sys.exit(app.exec_())
2、用鼠标点击按钮,会产生一个事件消息,操作系统接受事件消息,操作系统判断事件是发生在哪一个应用程序中,操作系统会把这个消息分发给该应用程序的消息队列。消息循环是由app.exec_()代码开启,不断扫描队列中的新消息,如果发现事件消息,则会包装成QEvent对象进行分发处理,分发给QApplication对象的notify中的(receiver,evt)方法。想查看是否接收到,可以重写notify方法,但他是系统的类,可以通过继承,在子类中重写。
from PyQt5.Qt import *
import sys
class App(QApplication):
# 方法的重写,一个是事件的接收者,一个是被包装的事件
# 优先调用子类的方法
def notify(self,receiver, evt):
# 过滤不需要的事件对象,只显示QPushButton按钮的事件
# 并过滤其他除鼠标按下事件的其他按事件
if receiver.inherits("QPushButton") and evt.type() == QEvent.MouseButtonPress:
print(receiver, evt)
# 继承父类的方法,分发事件,使事件传下去,
# 分发给事件接收者按钮,按钮中有evet方法
# 可以拦截but中的evt
return super().notify(receiver, evt)
class Btn(QPushButton):
# 很多事件都包含在其中,绘制事件、点击事件等
# evt具体的事件对象有很多类型
# 会根据evt的事件类型(鼠标事件、键盘事件)分发给receiver具体的事件函数
# 具体的事件函数,重写了btn的事件接收者方法,导致信号被覆盖,无法调用槽函数
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)
if __name__=="__main__":
# 创建app对象
#app = QApplication(sys.argv)
# 他会先使用App中的方法,如果子类没有,则会调用父类
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_())
用户点击某一个按钮产生的一个消息,所产生的一个事件消息都是通过层层分发达到信号发射步骤,任何一个环节出错,后续信号发射都会失败。
①首先在操作系统上跑一个软件,点击上边某一个按钮就会产生一个事件消息。
②事件消息先是被操作系统接收。
③操作系统会把事件消息分发到对应的应用程序的消息队列中。
④因为应用程序是在执行的,他有一个事件循环(事件循环主要检测消息队列中有没有新消息),消息队列中有新消息的话,把事件消息包装成一个QEvent对象,进行分发处理。
⑤分发其实是分发到了Application对象中的notify()方法。
⑥会根据receiver将事件传递给对应的对象进行处理。(事件接收者是谁就发给谁,例如按钮对象)
⑦默认在分发给对应对象的event方法,在该函数中会根据具体的事件类型进行分发(调用不同的事件函数,列入按下鼠标和点击调用不同的事件函数)。
⑧事件函数被调用之后会自己在向外界发射一个信号,然后连接信号所对应的槽函数才会被执行。(如果重写事件函数,该方法没有发出信号,则槽函数不会被执行)
故一般情况下能通过信号(对事件机制的封装)解决的问题就使用信号,如果无法解决就考虑使用事件解决。可以重写事件接收者的event等函数。也可以加载具体的事件函数中去修改。