Qt中postEvent和sendEvent函数

部分内容参考http://blog.csdn.net/lvmengzou/article/details/65450908

qt事件循环需要维护一个事件队列,在Qt的main函数中最后一般调用QApplication::exec()成员函数来保持程序对事件队列的处理,exec()的实质是不停调用processEvent()函数从队列中获取事件,并处理,然后删除,postEvent的作用就是发送一个事件到此队列中,由于删除队列中事件调用delete运算符,所以,postEvent()传递的事件一定要是动态分配的。

sendEvent()函数直接跳过事件循环队列,直接调用notify()函数发送事件到目标对象,并等待事件处理结果,所以其传递的事件直接在栈上分配即可,(postEvent()函数只负责添加事件到队列,不等待事件处理结果)。

sendEvent调用关系如下:

inline bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)

{ if (event) event->spont = false; return self ? self->notifyInternal(receiver, event) : false; }

QCoreApplication::notifyInternal(QObject * receiver, QEvent * event)

QCoreApplication::notify(QObject * receiver, QEvent *event)

QCoreApplicationPrivate::notify_helper(QObject * receiver, QEvent * event)

最终调用receiver->event(event);

PostEvent()函数只是单纯添加事件到postEventList

void QCoreApplication::postEvent(QObject *receiver, QEvent *event)

{

postEvent(receiver, event, Qt::NormalEventPriority);

}

void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)

{

...

QThreadData * volatile * pdata = &receiver->d_func()->threadData; //得到线程信息

QThreadData *data = *pdata;

if (!data) {

// posting during destruction? just delete the event to prevent a leak

delete event;

return;

}

// lock the post event mutex

data->postEventList.mutex.lock();

// if object has moved to another thread, follow it

while (data != *pdata) { //在这里判断receiver线程信息是否发生变化。(有可能是另外一个线程调用用receiver->moveToThread)

data->postEventList.mutex.unlock();

data = *pdata;

if (!data) {

// posting during destruction? just delete the event to prevent a leak

delete event;

return;

}

data->postEventList.mutex.lock();

}

//这里postEventList还是被锁着的。

// if this is one of the compressible events, do compression

if (receiver->d_func()->postedEvents

&& self && self->compressEvent(event, receiver, &data->postEventList)) {

data->postEventList.mutex.unlock();//这个事件有可能被压缩(实际上是发现队列中有这个事件还没有被处理,且这个事件是可以被压缩的,例如paintevent)

return;

}

event->posted = true;

++receiver->d_func()->postedEvents;

if (event->type() == QEvent::DeferredDelete && data == QThreadData::current()) {

// remember the current running eventloop for DeferredDelete

// events posted in the receiver's thread

event->d = reinterpret_cast(quintptr(data->loopLevel)); //receiver即将被析构?

}

//将事件添加到postEventList中,注意这里的优先级第一个最高,最后一个优先级最低

if (data->postEventList.isEmpty() || data->postEventList.last().priority >= priority) {

// optimization: we can simply append if the last event in

// the queue has higher or equal priority

data->postEventList.append(QPostEvent(receiver, event, priority));

} else {

// insert event in descending priority order, using upper

// bound for a given priority (to ensure proper ordering

// of events with the same priority)

QPostEventList::iterator begin = data->postEventList.begin()

+ data->postEventList.insertionOffset,

end = data->postEventList.end();

QPostEventList::iterator at = qUpperBound(begin, end, priority);

data->postEventList.insert(at, QPostEvent(receiver, event, priority));

}

data->canWait = false;

data->postEventList.mutex.unlock();//在这里解除锁

//receiver所在的线程调用eventDispatcher处理postEventList

if (data->eventDispatcher)

data->eventDispatcher->wakeUp();

}

如果想查看Qt中QApplication::exec()函数是如何传递事件到目标对象,并根据notify返回值和事件isAccept()的返回值决定是否传递事件到目标对象的父对象,可以重载目标对象的事件处理函数,并在事件处理函数中加入断点,开始调试,然后在可执行程序界面上触发事件处理函数,程序就会在事件处理函数的断点处停止,然后逐级返回,查看整个调用情况,从processEvent()函数到最终我们重载的事件处理函数,至少有20层函数调用。(调试之前要安装Qt源码组件)

qt中sendevent_Qt中postEvent和sendEvent函数相关推荐

  1. qt中sendevent_Qt Event Dispatcher学习

    距离上次整理Qt事件系统已经过了14个月了.重新理理思绪: Qt中的事件大致可分为3类: Spontaneous events 从系统得到的消息:鼠标按键.键盘按键.定时器事件等.转化为QEvent后 ...

  2. Qt中Ui名字空间以及setupUi函数的原理和实现

    Qt中Ui名字空间以及setupUi函数的原理和实现 分类: Qt GUI 2012-03-08 15:38 10514人阅读 评论(4) 收藏 举报 uiqtsignalclassdelete 用最 ...

  3. 【转】Qt调用dll中的功能函数

    DLL 优点 ------------------------------------- 1.扩展了应用程序的特性: 2.可以用许多种编程语言来编写: 3.简化了软件项目的管理: 4.有助于节省内存: ...

  4. qt在表格中如何画线_Qt之表格控件蚂蚁线

    阅读目录 回到顶部 一.蚂蚁线 摘自互动百科:在图像影像软件中表示选区的动态虚线,因为虚线闪烁的样子像是一群蚂蚁在跑,所以俗称蚂蚁线.在Poshop,After Effect等软件中比较常见. 背景: ...

  5. Qt模型视图中的委托

    文章目录 1 初探QT模型视图中的委托 2 自定义委托 3 深度解析视图与委托 3.1 实例1:自定义视图显示方式 3.2 实例2:自定义视图显示方式提升用户体验 1 初探QT模型视图中的委托 首先来 ...

  6. 记 QT 应用开发中的一个二进制兼容性问题

    笔者在参与开发一个集成了 QT 的跨平台桌面应用程序,目标平台是 Windows 和 Mac.一段时间以来,运行 Windows 平台的应用程序时,不断地被类似于如下这样的崩溃问题所折磨. 这里提示说 ...

  7. Qt学习之Qt基础入门(中)

    1. 前言 上一篇博客,总结了Qt的一些基础用法,这篇博客继续跟视频学习Qt的常用方法 Qt入门系列: Qt学习之C++基础 Qt学习之Qt安装 Qt学习之Qt基础入门(上) Qt学习之Qt基础入门( ...

  8. (二)Qt中QTableView中加入Check列实现

    QTableView中嵌入复选框CheckBox        第二种方法:设置QAbstractTableModel的flags()函数法 通过Delegate创建QCheckBox来实现的Chec ...

  9. Qt 多线程中地信号与槽

    Qt 多线程中地信号与槽 函数原型: 1 QObject::connect(const QObject *sender, const char *signal, const QObject *rece ...

最新文章

  1. Linux 计划任务整理
  2. 如何评价软件写的好还是坏?
  3. pythonpandas设置索引_python – pandas:使用(row,col)索引设置值
  4. spring-cloud Finchley.SR2版本 升级微服务到springboot 2.0
  5. java 关注公众号没有调接口_高频面试题:接口和抽象类的区别
  6. 002A demo of the Spectral Co-Clustering algorithm
  7. 【java笔记】线程间通信(2):生产者和消费者案例分析
  8. SpringBoot整合shiro框架(张开涛跟我学shiro-综合实例-代码新版)
  9. 基于python对B站缓存视频的批量复制,重命名
  10. android 读取本地超大图片
  11. 什么是网络号,主机号,主机地址,网络地址,主机地址,子网号,子网地址
  12. margin-left是什么意思
  13. 利用百度地图sdk实现定位
  14. jquery文字跳动js特效插件
  15. 树洞外链网盘系统php源码去除底部版权优化版
  16. P3345 [ZJOI2015]幻想乡战略游戏(动态点分治)
  17. jenkins_轮训SCM
  18. 刚听完CSDN总裁蒋涛先生的学术报告
  19. input file自定义
  20. lc振荡电路是如何起振的?

热门文章

  1. 【CF1189F】Array Beauty【dp】【复杂度玄学优化】
  2. P2257 YY的GCD
  3. QDU-Training-01
  4. [JSOI2007]字符加密
  5. YbtOJ#652-集合比较【Treap】
  6. 牛客小白月赛18-记录
  7. jzoj6375-华灵「蝶妄想」【结论题】
  8. POJ2481-Cows【树状数组】
  9. L. Mod(预处理+分块)
  10. 【最小生成树】路线规划(nowcoder 217603)