QT消息机制源码解析

当程序执行exec()后,程序进入事件循环

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    ...
    return a.exec();                   //调用QApplication:exec()函数,进入消息循环
}

进入QApplication::exec(),程序继续调用QCoreApplication::exec();

int QApplication::exec()
{
    ...
    return QCoreApplication::exec();     //继续调用QCoreApplication:exec()函数
}

进入QCoreApplication::exec(),程序继续调用QEventLoop::exec()函数;

int QCoreApplication::exec()
{
    ...
    int returnCode = eventLoop.exec();                //继续调用QEventLoop::exec();
    ...

    return returnCode;
}

进入QEvent::exec(),程序继续调用 QEventLoop::processEvents(ProcessEventsFlags flags)函数

int QEventLoop::exec(ProcessEventsFlags flags)
{
    ...
    try {
        while (!d->exit)
            processEvents(flags | WaitForMoreEvents | EventLoopExec);              //继续调用QEventLoop::processEvents(ProcessEventsFlags flags)函数
    } catch (...) {
        ...
    }

    return d->returnCode;
}

进入QEventLoop::processEvents(ProcessEventsFlags flags),继续调用QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)

bool QEventLoop::processEvents(ProcessEventsFlags flags)
{
    ...
    return d->threadData->eventDispatcher->processEvents(flags);        //继续调用QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)函数
}

进入QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags),首先通过PeekMessage获得获得系统消息,然后调用TranslateMessage与DispatchMessage翻译并分发消息

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

    if (!filterEvent(&msg)) {
        TranslateMessage(&msg);                    //翻译消息
        DispatchMessage(&msg);                     //分发消息
    }

    ...

    return retVal;
}

继续来看qt的widget是怎样响应系统的消息的

QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f)
    : QObject(dd, 0), QPaintDevice()
{
    ...

    d->init(parent, f);

    ...
}
void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
{
    ...

    if ((f & Qt::WindowType_Mask) == Qt::Desktop)
        q->create();
    ...
}
void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
{
    ...

    d->create_sys(window, initializeWindow, destroyOldWindow);

    ...
}
void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
{
    ...

    QString windowClassName = qt_reg_winclass(q);
    
    ...
}
const QString qt_reg_winclass(QWidget *w)        // register window class
{
    ...

    wc.lpfnWndProc  = (WNDPROC)QtWndProc;    //窗口过程

    ...
}
extern "C" LRESULT QT_WIN_CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    ...

    result = widget->translateMouseEvent(msg);        // mouse event
    
    ...
}
bool QETWidget::translateMouseEvent(const MSG &msg)
{
    ...
    
res = QApplicationPrivate::sendMouseEvent(target, &e, alienWidget, this, &qt_button_down, qt_last_mouse_receiver);
    
    ...
}
bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
                                         QWidget *alienWidget, QWidget *nativeWidget,
                                         QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver,
                                         bool spontaneous)
{
    ...

    if (spontaneous)
        result = QApplication::sendSpontaneousEvent(receiver, event);
    else
        result = QApplication::sendEvent(receiver, event);
    
    ...

    return result;
}
inline bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
{ 
    if (event) event->spont = false; return self ? self->notifyInternal(receiver, event) : false; 
}
bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event)
{
    ...

    QT_TRY {
        returnValue = notify(receiver, event);
    } QT_CATCH (...) {
        --threadData->loopLevel;
        QT_RETHROW;
    }

    ...
    return returnValue;
}
bool QCoreApplication::notify(QObject *receiver, QEvent *event)
{
    ...

    return receiver->isWidgetType() ? false : d->notify_helper(receiver, event);
}
bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)
{
    // send to all application event filters
    if (sendThroughApplicationEventFilters(receiver, event))    //qApplication的eventfilter()
        return true;
    // send to all receiver event filters
    if (sendThroughObjectEventFilters(receiver, event))         //接收widget的eventfilter()
        return true;
    // deliver the event
    return receiver->event(event);                              //接收widget的event()
}
bool QCoreApplicationPrivate::sendThroughApplicationEventFilters(QObject *receiver, QEvent *event)
{
    if (receiver->d_func()->threadData == this->threadData) {
        // application event filters are only called for objects in the GUI thread
        for (int i = 0; i < eventFilters.size(); ++i) {
            register QObject *obj = eventFilters.at(i);
            if (!obj)
                continue;
            if (obj->d_func()->threadData != threadData) {
                qWarning("QCoreApplication: Application event filter cannot be in a different thread.");
                continue;
            }
            if (obj->eventFilter(receiver, event))
                return true;
        }
    }
    return false;
}


bool QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject *receiver, QEvent *event)
{
    Q_Q(QCoreApplication);
    if (receiver != q) {
        for (int i = 0; i < receiver->d_func()->eventFilters.size(); ++i) {
            register QObject *obj = receiver->d_func()->eventFilters.at(i);
            if (!obj)
                continue;
            if (obj->d_func()->threadData != receiver->d_func()->threadData) {
                qWarning("QCoreApplication: Object event filter cannot be in a different thread.");
                continue;
            }
            if (obj->eventFilter(receiver, event))
                return true;
        }
    }
    return false;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt 事件循环机制Qt 框架的核心,它负责处理所有的事件和信号槽机制Qt 事件循环机制源码实现比较复杂,涉及到多个类和文件。下面是一个简单的 Qt 事件循环机制源码解析: 1. 事件循环机制的入口函数是 QCoreApplication::exec(),它是一个静态函数,会启动事件循环。 2. 在事件循环Qt 会不断地从事件队列取出事件,然后分发给对应的对象处理。事件队列是一个双向链表,由 QEventDispatcherWin32(Windows 平台)或 QEventDispatcherUNIX(Unix/Linux 平台)管理。 3. 事件分发的过程是通过 QObject::event() 函数实现的。当一个事件分发给一个对象时,它会首先调用对象的 event() 函数,如果该函数返回 false,那么事件会被传递给对象的父对象,直到有一个对象的 event() 函数返回 true,或者事件传递到了根对象。 4. 信号槽机制的实现也依赖于事件循环机制。当一个信号被发射时,它会被转化为一个事件,然后被插入到事件队列。当事件循环处理到该事件时,它会调用对应的槽函数。 5. 事件循环还涉及到消息循环和定时器机制消息循环通过 QSocketNotifier 和 QAbstractEventDispatcher 类实现,它可以监听文件描述符和套接字等事件。定时器机制通过 QTimer 类实现,它可以定时触发事件。 总之,Qt 事件循环机制源码实现非常复杂,但它是 Qt 框架的核心,负责处理所有的事件和信号槽机制,是 Qt 能够高效运行的关键。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值