大家都知道,QT的事件机制,查了好多网上的帖子,分析的不够到位,今天给大家分享下,我的分析,请高手指正:
都知道post Event通过
    QScopedPointer<QEvent> eventDeleter(event);
//增加到事件队列
    data->postEventList.addEvent(QPostEvent(receiver, event, priority));
    eventDeleter.take();
    event->posted = true;
    ++receiver->d_func()->postedEvents;
    data->canWait = false;
    locker.unlock();

//事件分发
    QAbstractEventDispatcher* dispatcher = data->eventDispatcher.loadAcquire();
    if (dispatcher)
        dispatcher->wakeUp();
网上基本上讲到这里,也就结束了,post Event由于是异步事件,很多都说和操作系统有关,这是对的,但是,还没有往下深纠,
下面我往下进行深入的考察:
QAbstractEventDispatcher,大家注意到这个类,这个类是一个抽象类,他是一个指针,指向的肯定是派生类。
他的派生类是什么呢?,他的派生类和平台相关,对于win下,他的派生类是QEventDispatcherWin32
这在QCore Application,就会创建,createEventDispatcher(),可以查看下这个里面的代码,

void QEventDispatcherWin32::wakeUp()
{
    Q_D(QEventDispatcherWin32);
    d->serialNumber.ref();
    if (d->internalHwnd && d->wakeUps.testAndSetAcquire(0, 1)) {
        // post a WM_QT_SENDPOSTEDEVENTS to this thread if there isn't one already pending
        PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0);
    }
}
这里里面调用的是PostMessage,这个是win32的标准函数,这个就把消息添加到,win32的消息列队里面去了。
到这里大家也许就不知道怎么办了,下面是什么呢?
别忘了,回掉函数,最终要通过回掉函数,来处理消息的。
LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
{
    if (message == WM_NCCREATE)
        return true;

MSG msg;
    msg.hwnd = hwnd;
    msg.message = message;
    msg.wParam = wp;
    msg.lParam = lp;
    QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance();
    long result;
    if (!dispatcher) {
        if (message == WM_TIMER)
            KillTimer(hwnd, wp);
        return 0;
    } else if (dispatcher->filterNativeEvent(QByteArrayLiteral("windows_dispatcher_MSG"), &msg, &result)) {
        return result;
    }

#ifdef GWLP_USERDATA
    QEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
#else
    QEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLong(hwnd, GWL_USERDATA);
#endif
    QEventDispatcherWin32Private *d = 0;
    if (q != 0)
        d = q->d_func();

if (message == WM_QT_SOCKETNOTIFIER) {
        // socket notifier message
        int type = -1;
        switch (WSAGETSELECTEVENT(lp)) {
        case FD_READ:
        case FD_ACCEPT:
            type = 0;
            break;
        case FD_WRITE:
        case FD_CONNECT:
            type = 1;
            break;
        case FD_OOB:
            type = 2;
            break;
        case FD_CLOSE:
            type = 3;
            break;
        }
        if (type >= 0) {
            Q_ASSERT(d != 0);
            QSNDict *sn_vec[4] = { &d->sn_read, &d->sn_write, &d->sn_except, &d->sn_read };
            QSNDict *dict = sn_vec[type];

QSockNot *sn = dict ? dict->value(wp) : 0;
            if (sn) {
#ifndef Q_OS_WINCE
                d->doWsaAsyncSelect(sn->fd, 0);
                d->active_fd[sn->fd].selected = false;
                d->postActivateSocketNotifiers();
#endif
                if (type < 3) {
                    QEvent event(QEvent::SockAct);
                    QCoreApplication::sendEvent(sn->obj, &event);
                } else {
                    QEvent event(QEvent::SockClose);
                    QCoreApplication::sendEvent(sn->obj, &event);
                }
            }
        }
        return 0;
#ifndef Q_OS_WINCE
    } else if (message == WM_QT_ACTIVATENOTIFIERS) {
        Q_ASSERT(d != 0);

// register all socket notifiers
        for (QSFDict::iterator it = d->active_fd.begin(), end = d->active_fd.end();
             it != end; ++it) {
            QSockFd &sd = it.value();
            if (!sd.selected) {
                d->doWsaAsyncSelect(it.key(), sd.event);
                sd.selected = true;
            }
        }
        d->activateNotifiersPosted = false;
        return 0;
#endif // !Q_OS_WINCE
    } else if (message == WM_QT_SENDPOSTEDEVENTS
               // we also use a Windows timer to send posted events when the message queue is full
               || (message == WM_TIMER
                   && d->sendPostedEventsWindowsTimerId != 0
                   && wp == (uint)d->sendPostedEventsWindowsTimerId)) {
        const int localSerialNumber = d->serialNumber.load();
        if (localSerialNumber != d->lastSerialNumber) {
            d->lastSerialNumber = localSerialNumber;
            q->sendPostedEvents();
        }
        return 0;
    } else if (message == WM_TIMER) {
        Q_ASSERT(d != 0);
        d->sendTimerEvent(wp);
        return 0;
    }

return DefWindowProc(hwnd, message, wp, lp);
}

最终通过回掉函数处理消息,回掉函数中调用sendPostedEvents,或者是sendEvent,而sendPostedEvents,最终调用会通过
QCore Application::sendPostedEvents();调用而这个有用到了sendEvent。
而大家都知道sendEvent是同步的。
这就是postEvent的整个过程

http://www.qtcn.org/bbs/apps.php?q=diary&uid=177993&a=detail&did=2356

QT5的post Event解析的更多相关文章

  1. C#事件(event)解析

    事件(event),这个词儿对于初学者来说,往往总是显得有些神秘,不易弄懂.而这些东西却往往又是编程中常用且非常重要的东西.大家都知道windows消息处理机制的重要,其实C#事件就是基于window ...

  2. CDI Event解析

    CDI(Contexts And Dependency Injection)是JavaEE 6标准中一个规范,将依赖注入IOC/DI上升到容器级别, 它提供了Java EE平台上服务注入的组件管理核心 ...

  3. C#事件(event)解析委托

    namespace Vczx.ProCSharp.Event { /// <summary> /// 类EatEventArgs 必须继承自类EventArgs,用来引发事件时封装数据 / ...

  4. Qt5 error LNK2019 无法解析的外部符号的解决办法

    今天在使用Qt Create 4.5.2时遇到一个莫名其妙的问题: 在原有工程里添加一个新类(有界面的),在调用的mainwindow.cpp中添加#include "a.h",然 ...

  5. VS2012 QT5.2.0 无法解析的外部符号

    背景:在新建QT工程时,可能没有选择一些库,虽然在头文件中引用了,但是程序依然无法识别 现象:一般出现"LNK2019"错误. 解决:以网络为例,在VS2012中加入网络库,分为两 ...

  6. 深入解析MySQL replication协议

    Why 最开始的时候,go-mysql只是简单的抽象mixer的代码,提供一个基本的mysql driver以及proxy framework,但做到后面,笔者突然觉得,既然研究了这么久mysql c ...

  7. 处理事件的方式:两种类的覆盖处理(自己管理,覆盖专用事件函数;自己统一管理,覆盖QWidget::Event通用函数),一种对象的处理(父控件统一管理,即安装过滤器),两种全局处理(QCoreApplication安装过滤器;覆盖notify方法)

    虽然只有一句话,但却是我自己的心得. 特别注意,bool QCoreApplication::notify(QObject *receiver, QEvent *event) 明确指明了要发送的对象, ...

  8. MySQL Binlog解析

    https://yq.aliyun.com/articles/238364?spm=5176.8067842.tagmain.52.73PjU3 摘要: 概述 MySQL的安装可以参考:Linux(C ...

  9. C# 事件 event 【转】

    C#事件(event)解析   事件(event),这个词儿对于初学者来说,往往总是显得有些神秘,不易弄懂.而这些东西却往往又是编程中常用且非常重要的东西.大家都知道windows消息处理机制的重要, ...

随机推荐

  1. iOS QLPreviewController(Quick Look)快速浏览jpg,PDF,world等

    #import <QuickLook/QuickLook.h> @interface ViewController ()<QLPreviewControllerDataSource, ...

  2. 文件控制 fcntl函数具体解释

    摘要:本文主要讨论文件控制fcntl函数的基本应用.dup函数能够拷贝文件描写叙述符,而fcntl函数与dup函数有着异曲同工之妙.而且还有更加强大的功能,能够获取或设置已打开文件的性质,操作文件锁. ...

  3. cordova 生成发行版apk,并添加证书 – 畅玩Coding

    原文:cordova 生成发行版apk,并添加证书 – 畅玩Coding 首先jdk生成证书. 1.进入jdk安装目录 D:\Java\jdk1.7.0\bin 2.执行命令 keytool -gen ...

  4. zookeeper 分布式安装/配置/启动

    版本3.4.10,已提前配置好jdk 三台主机:hadoop002,hadoop003.hadoop004 1.配置 将zookeeper-3.4.10.tar.gz解压后进入zookeeper-3. ...

  5. 【23.33%】【hdu 5945】Fxx and game

    Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) Total Submission(s ...

  6. Tower与DevCloud对比分析报告

    1. 产品介绍 Tower是彩程设计公司出品的远程办公和团队协作工具,为小企业和小团队提供简单.靠谱的在线协作服务. DevCloud是集华为研发实践.前沿研发理念.先进研发工具为一体的研发云平台.D ...

  7. NET媒体文件操作组件TagLib

    开源的.NET媒体文件操作组件TagLib#解析   人生得意须尽欢 莫使金樽空对月.写博客都会在吃饭后,每次吃饭都要喝上二两小酒,写博客前都要闲扯,这些都是个人爱好,改不掉了,看不惯的人,还望多多包 ...

  8. 【24.63%】【codefroces 686D】Kay and Snowflake

    time limit per test 3 seconds memory limit per test 256 megabytes input standard input output standa ...

  9. 打开一个很好的介绍Lucene4 FST文章

    我没有看到源代码.看到这个博客了解一些基本的,像笔者下: http://download.csdn.net/download/guanxinquan/7380591 http://blog.sina. ...

  10. Application与Context关联

    在发展中Application分类,几乎每个项目将用于,它的四个组成部分的实施优化,它是一个全球性的框,这可能是这么理解,例如,我们可以application类存储一些变量,在其他类访问,例如,在A类 ...