• Qt 事件循环


    引出

            UI程序之所叫UI程序,是因为需要与用户有交互,用户交互一般是通过鼠标键盘等的输入设备,那UI程序就需要有能随时响应用户交互的能力。

    一个C++程序的main函数大概是下面这样:

    1. int main()
    2. {
    3. ...
    4. return 0;
    5. }

    我们如何使程序能随时可以响应用户交互呢?一个比较简单的设计就是通过while循环:

    1. int main()
    2. {
    3. while (1) {
    4. 获取用户输入;
    5. 处理用户输入;
    6. }
    7. return 0;
    8. }

    有时一个事件的处理可能稍微会多花一点时间,如果是上面这样,在处理一个事件时就不能响应其他事件了,所以我们需要一个队列,系统可以将新事件放到队列里:

    1. int main()
    2. {
    3. while(1) {
    4. event = getEventFromQueue()
    5. dealEvent(event);
    6. }
    7. }

    原理

            在Qt中,事件循环是一种机制,用于处理各种异步事件。事件循环通过一个事件队列来管理和调度事件,当队列中有事件时,事件循环会从队列中依次取出事件并处理,直到队列为空或者事件循环被中断

            事件循环首先是一个无限“循环”,程序在exec()里面无限循环,能让跟在exec()后面的代码得不到运行机会,直至程序从exec()跳出。从exec()跳出时,事件循环即被终止。

            其次,之所以被称为“事件”循环,是因为它能接收事件,并处理之。当事件太多而不能马上处理完的时候,待处理事件被放在一个“队列”里,称为“事件循环队列”。当事件循环处理完一个事件后,就从“事件循环队列”中取出下一个事件处理之。当事件循环队列为空的时候,它和一个啥事也不做的永真循环有点类似,但是和永真循环不同的是,事件循环不会大量占用CPU资源。事件循环的本质就是以队列的方式再次分配线程时间片。

    事件是如何产生的?

            事件的产生可以分为两种:

            程序外部产生:指系统产生的事件,例如鼠标按下(MouseButtonPress)、按键按下(KeyPress)等。Qt通过捕捉系统事件,将其封装成自己的QEvent类,再将事件发送出去。

            程序内部产生:指在代码中手动创建一个事件,然后通过sendEvent/postEvent将事件发送到事件循环中。其中,sendEvent是阻塞型的发送方式,会等待事件处理完成后再继续执行;而postEvent是非阻塞型的发送方式,会将事件放入事件队列中,并立即返回。

    本质

            QEventLoop即Qt中的事件循环类。主要接口如下:

    1. //exec是启动事件循环,调用exec以后,调用exec的函数就会被“阻塞”,直到EventLoop里面的while循环结束。
    2. int exec(QEventLoop::ProcessEventsFlags flags = AllEvents)
    3. //exit是退出事件循环;
    4. void exit(int returnCode = 0)
    5. bool isRunning() const
    6. //processEvents是及时处理队列中的事件(这个很有用)
    7. bool processEvents(QEventLoop::ProcessEventsFlags flags = AllEvents)
    8. void processEvents(QEventLoop::ProcessEventsFlags flags, int maxTime)
    9. void wakeUp()

    示意图:

            这里有个问题,exec阻塞了当前函数,还怎么退出EventLoop呢?

            答案是:在派发事件后,某个事件处理的函数中,达到事件退出条件时,调用exit函数,将EventLoop中的退出标识设为true。

            一般的Qt程序,main函数中都有一个QCoreApplication/QGuiApplication/QApplication,并在末尾调用 exec。

            创建Qt Core Application时使用的是QCoreApplication,创建Qt Widgets Application时使用的是QApplication,创建Qt Quick Application时使用的是QGuiApplication。

    其他

    1. //例1:
    2. int main(int argc, char *argv[])
    3. {
    4. QApplication a(argc, argv);
    5. Widget_ScrollBar w;
    6. w.show();
    7. /*w.show()不生效;界面不会输出;UI程序中事件循环实质是:通过UI来进行事件的循环处理*/
    8. //return a.exec();
    9. return 0;
    10. }
    11. //例2:
    12. int main(int argc, char *argv[])
    13. {
    14. QApplication a(argc, argv);
    15. Widget_ScrollBar w;
    16. w.show();
    17. a.exec();//阻塞后续程序执行
    18. /*只有exec()退出,事件循环结束,才会输出Hello World*/
    19. qDebug() << "Hello World";
    20. return 0;
    21. }

  • 相关阅读:
    18 【移动Web开发之流式布局】
    如何用selenium或pyppeteer来链接并打开指纹浏览器AdsPower
    【001_音频开发-基础篇-专业术语】
    内网穿透到公网,让你的小伙伴访问你本地的项目
    智慧运维解决方案-最新全套文件
    Jetpack 多个Activity共享ViewModel(AndroidViewModel)
    鸿蒙操作系统 HarmonyOS 3.2 API 9 Stage模型通过ArkTS接入高德地图
    基于STM32设计的酒驾监控系统_优化升级版
    进行日常记账后,怎样导出表格
    剑指Offer || 041.数据流中的移动平均值
  • 原文地址:https://blog.csdn.net/hao745580264_dawei/article/details/134333498