QT事件处理-事件机制(二)

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等函数。也可以加载具体的事件函数中去修改。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

。七十二。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值