QT事件循环机制源码学习

文章目录

QT源码中事件梳理过程中调用函数如下:

1.app.exec(); 开启应用程序的事件循环

cpp 复制代码
    QApplication app(argc, argv);
    return app.exec();

2. int QCoreApplication::exec()

3.使用QEventLoop开启事件循环

cpp 复制代码
    QEventLoop eventLoop;
    self->d_func()->in_exec = true;
    self->d_func()->aboutToQuitEmitted = false;
    int returnCode = eventLoop.exec();

4.bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)

  • QEventDispatcherWin32 是 Qt 框架中事件调度器的一个具体实现,用于 Windows 平台。它是QAbstractEventDispatcher 的子类,负责管理 Qt 应用程序的事件循环在 Windows 上的运行。linux平台是类QEventDispatcherUNIX
  • 负责 Qt 应用程序在 Windows 上的主事件循环
  • 处理 Windows 消息与 Qt 事件的转换和分发
  • 是 QApplication::exec() 在 Windows 上的底层实现
  • 通过打断点也可以看到开启事件循环后程序会持续进入这个函数QEventDispatcherWin32::processEvents
cpp 复制代码
class Q_CORE_EXPORT QEventDispatcherWin32 : public QAbstractEventDispatcher
{
    Q_OBJECT
    Q_DECLARE_PRIVATE(QEventDispatcherWin32)
    
    ......

5.以鼠标点击为例,windows是如何将鼠标点击的系统消息转化到Qt可识别的事件类型

cpp 复制代码
1.extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

2.bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
                                  QtWindows::WindowsEventType et,
                                  WPARAM wParam, LPARAM lParam,
                                  LRESULT *result,
                                  QWindowsWindow **platformWindowPtr)


// 将操作系统打包的事件解包、翻译为QApplication可识别的事件
3.bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
                                               QtWindows::WindowsEventType et,
                                               MSG msg, LRESULT *result)

4.QWindowSystemInterface::handleMouseEvent(window, clientPosition, globalPosition, buttons, m_lastEventButton,
                                                         QEvent::MouseButtonRelease, keyModifiers, source);
                                                         
5.void QWidgetWindow::handleMouseEvent(QMouseEvent *event)

6.bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
                                         QWidget *alienWidget, QWidget *nativeWidget,
                                         QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver,
                                         bool spontaneous, bool onlyDispatchEnterLeave)
// 系统鼠标、键盘消息一般都是此接口  
7.QApplication::sendSpontaneousEvent(receiver, event);

8.bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event)
{
    Q_TRACE(QCoreApplication_sendSpontaneousEvent, receiver, event, event->type());

    if (event)
        event->spont = true;
    return notifyInternal2(receiver, event);
}

6.bool QCoreApplication::notifyInternal2(QObject *receiver, QEvent *event)

7.bool QCoreApplication::notify(QObject *receiver, QEvent *event)

8.bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)

  • 向事件过滤器发送该事件,这里介绍一下Event Filters. 事件过滤器是一个接受即将发送给目标对象所有事件的对象。
  • 如代码所示它开始处理事件在目标对象行动之前。过滤器的 QObject::eventFilter()实现被调用,能接受或者丢弃过滤
  • 允许或者拒绝事件的更进一步的处理。如果所有的事件过滤器允许更进一步的事件处理,事件将被发送到目标对象本身。
  • 如果他们中的一个停止处理,目标和任何后来的事件过滤器不能看到任何事件。
cpp 复制代码
bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)
{
    // Note: when adjusting the tracepoints in here
    // consider adjusting QApplicationPrivate::notify_helper too.
    Q_TRACE(QCoreApplication_notify_entry, receiver, event, event->type());
    bool consumed = false;
    bool filtered = false;
    Q_TRACE_EXIT(QCoreApplication_notify_exit, consumed, filtered);

    // send to all application event filters (only does anything in the main thread)
    if (QCoreApplication::self
            && receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread()
            && QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event)) {
        filtered = true;
        return filtered;
    }
    // 这个函数中会访问receiver(目标对象)的过滤器,判断是否需要过滤此事件,return true就是过滤掉 false则是不过滤会真正传递给receiver(目标对象)
    if (sendThroughObjectEventFilters(receiver, event)) {
        filtered = true;
        return filtered;
    }

 // receiver(目标对象)的事件处理函数被真正得到执行
    consumed = receiver->event(event);
    return consumed;
}

9.事件派发至目标对象QObject的子类,这里以QWidget为例

cpp 复制代码
bool QWidget::event(QEvent *event)
{
    ...
 
    switch (event->type()) {
    case QEvent::MouseMove:
        mouseMoveEvent((QMouseEvent*)event);
        break;
 
    case QEvent::MouseButtonPress:
 #if 0
        resetInputContext();
 #endif
        mousePressEvent((QMouseEvent*)event);
        break;
        ...
}
相关推荐
老王爱玩车9 分钟前
深入理解指针2
c语言·开发语言·学习
quantdash_cc13 分钟前
股票历史数据为什么比实时行情更重要?回测结果失真的根源可能就在 K 线数据
开发语言·python·数据分析·量化交易·股票数据·quantdash
光电的一只菜鸡25 分钟前
为什么调整LSC会对AF产生影响
android·开发语言·kotlin
zhangjw3428 分钟前
第47篇:Java综合实战:电商秒杀系统(高并发场景)
java·开发语言
FOAF-lambda1 小时前
uiautomation-new 控件方位的使用
开发语言·python
OKkankan1 小时前
LangChain能力详解!:从工具调用到 LangSmith——让聊天模型具备实时交互能力!
开发语言·python·langchain
richard_yuu1 小时前
AOI 实战第五篇:c_broken 漏检严重,V4 迭代背后的权衡
开发语言·深度学习·yolo
那年窗外下的雪.1 小时前
AIDC 学习日志|第 22 天|All-Active/Single-Active 故障演练设计
服务器·网络·学习·算法·哈希算法
m0_734571761 小时前
深入理解C++ 析构函数<一>基本概念
开发语言·c++