QT5的post Event解析
大家都知道,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解析的更多相关文章
- C#事件(event)解析
事件(event),这个词儿对于初学者来说,往往总是显得有些神秘,不易弄懂.而这些东西却往往又是编程中常用且非常重要的东西.大家都知道windows消息处理机制的重要,其实C#事件就是基于window ...
- CDI Event解析
CDI(Contexts And Dependency Injection)是JavaEE 6标准中一个规范,将依赖注入IOC/DI上升到容器级别, 它提供了Java EE平台上服务注入的组件管理核心 ...
- C#事件(event)解析委托
namespace Vczx.ProCSharp.Event { /// <summary> /// 类EatEventArgs 必须继承自类EventArgs,用来引发事件时封装数据 / ...
- Qt5 error LNK2019 无法解析的外部符号的解决办法
今天在使用Qt Create 4.5.2时遇到一个莫名其妙的问题: 在原有工程里添加一个新类(有界面的),在调用的mainwindow.cpp中添加#include "a.h",然 ...
- VS2012 QT5.2.0 无法解析的外部符号
背景:在新建QT工程时,可能没有选择一些库,虽然在头文件中引用了,但是程序依然无法识别 现象:一般出现"LNK2019"错误. 解决:以网络为例,在VS2012中加入网络库,分为两 ...
- 深入解析MySQL replication协议
Why 最开始的时候,go-mysql只是简单的抽象mixer的代码,提供一个基本的mysql driver以及proxy framework,但做到后面,笔者突然觉得,既然研究了这么久mysql c ...
- 处理事件的方式:两种类的覆盖处理(自己管理,覆盖专用事件函数;自己统一管理,覆盖QWidget::Event通用函数),一种对象的处理(父控件统一管理,即安装过滤器),两种全局处理(QCoreApplication安装过滤器;覆盖notify方法)
虽然只有一句话,但却是我自己的心得. 特别注意,bool QCoreApplication::notify(QObject *receiver, QEvent *event) 明确指明了要发送的对象, ...
- MySQL Binlog解析
https://yq.aliyun.com/articles/238364?spm=5176.8067842.tagmain.52.73PjU3 摘要: 概述 MySQL的安装可以参考:Linux(C ...
- C# 事件 event 【转】
C#事件(event)解析 事件(event),这个词儿对于初学者来说,往往总是显得有些神秘,不易弄懂.而这些东西却往往又是编程中常用且非常重要的东西.大家都知道windows消息处理机制的重要, ...
随机推荐
- Mac下新安装的MySQL无法登陆root用户(安装时没有设置密码)
1.也不知是何原因,新安装好的MySQL,如果尝试用mysql -u root -p登陆就会出现这样的错误,但是root用户根本就没有设置密码. $ cd /usr/local$ cd mysql $ ...
- 【rlz000】字串找数
Time Limit: 3 second Memory Limit: 2 MB 问题描述 输入一个字符串,内有数字和非数字字符.如A123X456Y7A,302ATB567BC,统计共有多少个整数, ...
- Less小总结
= 导航 顶部 变量 混合 继承 函数 顶部 变量 混合 继承 函数 Less 是一个Css 预编译器,意思指的是它可以扩展Css语言,添加功能如允许变量(variables),混合(mi ...
- 从Client应用场景介绍IdentityServer4(三)
原文:从Client应用场景介绍IdentityServer4(三) 在学习其他应用场景前,需要了解几个客户端的授权模式.首先了解下本节使用的几个名词 Resource Owner:资源拥有者,文中称 ...
- phpstudy2018升级MySQL5.5为5.7.24教程(图文)
原文: phpstudy2018升级MySQL5.5为5.7教程(图文) 一.MySQL官网下载MySQL5.7版本,我这里下载的是MySQL5.7.24. 二.直接到D:phpStudyPHPTut ...
- 《得知opencv》注意事项——矩阵和图像处理——cvAdd、cvAddS and cvAddWeighted
矩阵和图像操作 (1)cvAdd函数 其结构 void cvAdd(//图像加和 const CvArr* src1,//第一个原矩阵 const CvArr* src2,//第二个原矩阵 CvArr ...
- SecureCRT 专题
SecureCRT在同一窗口打开多个标签:选中“在标签页中打开”即可 SecureCRT同时向多个tab窗口发送相同的命令 Step by step: 作为管理N台服务器,而又要执行相同命令又不想用脚 ...
- WPF制作的党旗
原文:WPF制作的党旗 --------------------------------------------------------------------------------引用或转载时请保 ...
- (记录)mysql分页查询,参数化过程的坑
在最近的工作中,由于历史遗留,一个分页查询没有参数化,被查出来有sql注入危险,所以对这个查询进行了参数化修改. 一看不知道,看了吓一跳,可能由于种种原因,分页查询sql是在存储过程中拼接出来的,wh ...
- Matlab Tricks(二十二)—— 自定义函数
printme = @(txt) print('-dpdf', sprintf('figures/Example_%s',txt)); % 这里的 print 显然不是控制台输出一句话,而是图像的命名 ...