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;
        ...
}
相关推荐
A.A呐7 小时前
【C++第二十九章】IO流
开发语言·c++
椰猫子7 小时前
Java:异常(exception)
java·开发语言
lifewange7 小时前
pytest-类中测试方法、多文件批量执行
开发语言·python·pytest
cmpxr_8 小时前
【C】原码和补码以及环形坐标取模算法
c语言·开发语言·算法
2401_827499998 小时前
python项目实战09-AI智能伴侣(ai_partner_5-6)
开发语言·python
PD我是你的真爱粉8 小时前
MCP 协议详解:从架构、工作流到 Python 技术栈落地
开发语言·python·架构
龙文浩_8 小时前
Attention Mechanism: From Theory to Code
人工智能·深度学习·神经网络·学习·自然语言处理
星晨雪海8 小时前
基于 @Resource 的支付 Service 多实现类完整示例
java·开发语言
ACP广源盛139246256739 小时前
破局 Type‑C 切换器痛点@ACP#GSV6155+LH3828/GSV2221+LH3828 黄金方案
c语言·开发语言·网络·人工智能·嵌入式硬件·计算机外设·电脑
Ricky_Theseus9 小时前
C++右值引用
java·开发语言·c++