• Qt 事件处理机制简介


    1.Qt中事件的来源,谁接收处理。

    Qt中事件的来源有两个:程序外部和内部,多数情况下来自操作系统,可以通过bool QEvent::spontaneous() const函数来获知,返回true,事件发生在应用程序之外(系统事件),否则返回false。

    事件由QObject类来接收,是Qt对象模型的核心,所有需要处理的事件类都必须继承QObject。

    2.事件处理顺序

    首先QCoreApplication::exec()开启了事件循环,一直到QCoreApplication::exit()被调用才终止,所以说事件循环是伴随着Qt程序的整个运行周期,事件被分发到事件队列中,当队列中有事件时会不停的将事件发送给QObject对象,队列为空时就阻塞,以下为处理顺序。

    sendEvent:使用notify()函数直接将事件发送给接收者,发送事件时不会删除该事件,通常是在栈上面创建事件,它是同步事件。

    postEvent:将事件添加到事件队列中,并立即返回;事件必须在堆上分配,因为提交事件队列将获得事件的所有权,并在提交后删除它。在事件发布后访问该事件是不安全的,它是异步事件。

    本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QT嵌入式开发,Quick模块等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

    示例:

    1. void Widget::on_pushButton_clicked()
    2. {
    3. QKeyEvent eventPress(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier);
    4. QApplication::sendEvent(ui->label, &eventPress);
    5. }
    6. void Widget::on_pushButton_2_clicked()
    7. {
    8. QKeyEvent *eventPress = new QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier);
    9. QApplication::postEvent(ui->label, eventPress);
    10. }

    点击上图中按钮会发送QLabel标签的键盘按下tab键事件,我自定义了一个WLabel类继承自QLabel,重写了event方法。

    1. bool WLabel::event(QEvent *e)
    2. {
    3. if(e->type() == QEvent::KeyPress)
    4. {
    5. QKeyEvent *keyEvent = (QKeyEvent*)e;
    6. if(keyEvent->key() == Qt::Key_Tab)
    7. {
    8. qDebug()<<"press tab key";
    9. return ture;
    10. }
    11. }
    12. return QLabel::event(e);
    13. }

    事件会发送到WLabel类的event方法中,会打印出下面的结果。

     

    3.事件过滤器

    事件的传送和处理流程的第一站是事件过滤器eventFilter(),某个对象A可以通过给另一个对象B安装事件处理器,实现对对象B事件的监听或者拦截功能。我们可以给A取名监听器,B取名接收器。一个对象可以监听多个对象,一个对象也可以被多个事件监听。事件过滤器返回true则表示事件已经处理完毕,否则传递给下一个监听器或者接收器本身。

    void QObject::installEventFilter(QObject *filterObj)
    bool eventFilter(QObject *obj, QEvent *event);

    Qt的事件过滤由以上两个方法实现,首先安装一个事件过滤器,然后重写bool eventFilter(QObject *obj, QEvent *event)。

    filterObj表示事件筛选器对象,它接收发送到此QObject对象的所有事件。筛选器可以停止事件,也可以将事件转发给此QObject对象。事件过滤器filterObj通过它的eventFilter()函数接收事件。

    eventFilter()有返回值。

    如果返回true,表示事件过滤,不会发送到对象本身。

    如果返回false,表示事件未过滤,会通过event()方法将事件分发到对象。

    返回给基类进行处理,例:return QObject::eventFilter(obj, event)。

    4.event方法

    当经过事件过滤器后,未过滤掉的事件会进入到event方法中,event()函数主要用于事件的分发。所以,如果你希望在事件分发之前做一些操作,就可以在派生类中重写这个event()函数。

    例:实现一些鼠标进出的打印,键盘按键一些打印。

    1. bool WLabel::event(QEvent *e)
    2. {
    3. if(e->type() == QEvent::Enter)
    4. {
    5. qDebug()<<"WLabel event :enter";
    6. return true;
    7. }
    8. else if(e->type() == QEvent::Leave)
    9. {
    10. qDebug()<<"WLabel event :Leave";
    11. return true;
    12. }
    13. else if(e->type() == QEvent::KeyPress)
    14. {
    15. QKeyEvent *keyEvent = (QKeyEvent*)e;
    16. if(keyEvent->key() == Qt::Key_Tab)
    17. {
    18. qDebug()<<"press tab key";
    19. return true;
    20. }
    21. }
    22. return QLabel::event(e);
    23. }

    上述代码中event如果事件e被识别并处理,则应返回true,否则交给它的基类QLabel来处理。

    5.鼠标进入事件

    1. bool WLabel::event(QEvent *e)
    2. {
    3. if(e->type() == QEvent::Enter)
    4. {
    5. qDebug()<<"WLabel event :enter";
    6. }
    7. return QLabel::event(e);
    8. }

    上述代码,

    • 如果事件返回return QLabel::event(e),会将鼠标进入事件分发到 enterEvent(QEvent *event),会打印下面的语句。
    • 如果打印语句后面 return ture,则不会将事件传递到enterEvent中。
    1. void WLabel::enterEvent(QEvent *event)
    2. {
    3. qDebug()<<"WLabel enterEvent";
    4. }

    6.accept(),ignore()

    在我们做UI界面时,经常会重写mousePressEvent,wheelEvent等函数,根据不同情况要对事件event进行特殊处理。

    当执行event->accept()时,意味着这次的事件已经被“我”接受啦,只有我使用。

    当执行event->ignore()时,意味着这次的事件“我”不要接受他,函数执行完event给我的父窗口,他会需要的。

    差别也就是要不要传递给父窗口,accept不传递,ignore传递,注意是父窗口,不是基类。

    本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QT嵌入式开发,Quick模块等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

  • 相关阅读:
    【绘图案例-绘图的步骤 Objective-C语言】
    巧妙利用unbuffer实时写入
    JAVA-Map接口概述、常用方法、排序、Hashtable面试题
    Windows10电脑没有微软商店的解决方法
    记录一次Maven依赖传递,模块之间依赖版本不一致问题
    提升品牌形象:利用OLED透明拼接屏进行品牌展示
    在el-table表头上引入组件不能实时传参bug
    java疫情期间社区出入管理系统-计算机毕业设计源码21295
    linux 进程 CPU耗费较高排查
    车载 SOME/IP测试 上手整理 - 一万三千字
  • 原文地址:https://blog.csdn.net/m0_60259116/article/details/127941771