Qt中事件分发源码剖析
Qt中事件分发源码剖析
Qt中事件传递顺序:
在一个应该程序中,会进入一个事件循环,接受系统产生的事件,而且进行分发,这些都是在exec中进行的。
以下举例说明:
1)首先看看以下一段演示样例代码:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MouseEvent w;
w.show(); return a.exec();
}
2)a.exec进入事件循环,调用的是QApplication::exec();
int QApplication::exec()
{
return QGuiApplication::exec();
}
3)QApplication::exec()调用的是QGuiApplication::exec();
int QGuiApplication::exec()
{
#ifndef QT_NO_ACCESSIBILITY
QAccessible::setRootObject(qApp);
#endif
return QCoreApplication::exec();
}
4)QGuiApplication::exec()调用的是QCoreApplication::exec();
int QCoreApplication::exec()
{
if (!QCoreApplicationPrivate::checkInstance("exec"))
return -1; QThreadData *threadData = self->d_func()->threadData;
if (threadData != QThreadData::current()) {
qWarning("%s::exec: Must be called from the main thread", self->metaObject()->className());
return -1;
}
if (!threadData->eventLoops.isEmpty()) {
qWarning("QCoreApplication::exec: The event loop is already running");
return -1;
} threadData->quitNow = false;
QEventLoop eventLoop;
self->d_func()->in_exec = true;
self->d_func()->aboutToQuitEmitted = false;
int returnCode = eventLoop.exec();
threadData->quitNow = false;
if (self) {
self->d_func()->in_exec = false;
if (!self->d_func()->aboutToQuitEmitted)
emit self->aboutToQuit(QPrivateSignal());
self->d_func()->aboutToQuitEmitted = true;
sendPostedEvents(0, QEvent::DeferredDelete);
} return returnCode;
}
5)QCoreApplication::exec()调用eventLoop.exec()进行事件循环;
int QEventLoop::exec(ProcessEventsFlags flags)
{
Q_D(QEventLoop);
//we need to protect from race condition with QThread::exit
QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread))->mutex);
if (d->threadData->quitNow)
return -1; if (d->inExec) {
qWarning("QEventLoop::exec: instance %p has already called exec()", this);
return -1;
} struct LoopReference {
QEventLoopPrivate *d;
QMutexLocker &locker; bool exceptionCaught;
LoopReference(QEventLoopPrivate *d, QMutexLocker &locker) : d(d), locker(locker), exceptionCaught(true)
{
d->inExec = true;
d->exit = false;
++d->threadData->loopLevel;
d->threadData->eventLoops.push(d->q_func());
locker.unlock();
} ~LoopReference()
{
if (exceptionCaught) {
qWarning("Qt has caught an exception thrown from an event handler. Throwing\n"
"exceptions from an event handler is not supported in Qt. You must\n"
"reimplement QApplication::notify() and catch all exceptions there.\n");
}
locker.relock();
QEventLoop *eventLoop = d->threadData->eventLoops.pop();
Q_ASSERT_X(eventLoop == d->q_func(), "QEventLoop::exec()", "internal error");
Q_UNUSED(eventLoop); // --release warning
d->inExec = false;
--d->threadData->loopLevel;
}
};
LoopReference ref(d, locker); // remove posted quit events when entering a new event loop
QCoreApplication *app = QCoreApplication::instance();
if (app && app->thread() == thread())
QCoreApplication::removePostedEvents(app, QEvent::Quit); while (!d->exit)
processEvents(flags | WaitForMoreEvents | EventLoopExec); ref.exceptionCaught = false;
return d->returnCode;
}
6)eventLoop.exec()调用QCoreApplication的processEvents进行事件分发;
7)调用notify进行分发
QCoreApplication::sendEvent、QCoreApplication::postEvent和QCoreApplication::sendPostedEvents都调用notify进行事件分发;
bool QCoreApplication::notify(QObject *receiver, QEvent *event)
{
Q_D(QCoreApplication);
// no events are delivered after ~QCoreApplication() has started
if (QCoreApplicationPrivate::is_app_closing)
return true; if (receiver == 0) { // serious error
qWarning("QCoreApplication::notify: Unexpected null receiver");
return true;
} #ifndef QT_NO_DEBUG
d->checkReceiverThread(receiver);
#endif return receiver->isWidgetType() ? false : d->notify_helper(receiver, event);
}
8)notify调用notify_helper进行事件分发;
bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)
{
// send to all application event filters
if (sendThroughApplicationEventFilters(receiver, event))
return true;
// send to all receiver event filters
if (sendThroughObjectEventFilters(receiver, event))
return true;
// deliver the event
return receiver->event(event);
}
9)从上面第8步的代码能够看出事件传递
传递的顺序是:首先传递给全局的事件过滤器,再传递给目标对象的事件过滤器,终于传递给目标对象。
Qt中事件分发源码剖析的更多相关文章
- ViewGroup事件分发源码分析
1.AndroidStudio源码调试方式 AndroidStudio默认是支持一部分源码调试的,但是build.gradle(app) 中的sdk版本要保持一致, 最好是编译版本.运行版本以及手机的 ...
- Android View事件分发源码分析
引言 上一篇文章我们介绍了View的事件分发机制,今天我们从源码的角度来学习下事件分发机制. Activity对点击事件的分发过程 事件最先传递给当前Activity,由Activity的dispat ...
- android事件分发源码分析—笔记
昨天晚上从源码角度复习了一下android的事件分发机制,今天将笔记整理下放在网上.其实说复习,也是按着<android开发艺术探索>这本书作者的思路做的笔记. 目录 事件是如何从Acti ...
- view事件分发源码理解
有些困难无法逃避,没办法,那就只有去解决它.view事件分发对我而言是一块很难啃的骨头,看了<安卓开发艺术探索>关于这个知识点的讲解,看了好几遍,始终不懂,最终通过调试分析结果,看博客,再 ...
- Touch事件分发源码解析
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 以下源码基于Gingerbread 2.3.7 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1.先看ViewGroup的di ...
- Qt中事件分发源代码剖析(一共8个步骤,顺序非常清楚:全局的事件过滤器,再传递给目标对象的事件过滤器,最终传递给目标对象)
Qt中事件分发源代码剖析 Qt中事件传递顺序: 在一个应该程序中,会进入一个事件循环,接受系统产生的事件,并且进行分发,这些都是在exec中进行的.下面举例说明: 1)首先看看下面一段示例代码: in ...
- Qt中事件分发源代码剖析
Qt中事件分发源代码剖析 Qt中事件传递顺序: 在一个应该程序中,会进入一个事件循环,接受系统产生的事件,并且进行分发,这些都是在exec中进行的. 下面举例说明: 1)首先看看下面一段示例代码: i ...
- QT中事件处理器和事件过滤器实现实例
Qt中事件处理的方式,最常用的就是使用事件处理器(event handler)和事件过滤器(event filter)这两种方法.接下来,我们就来看看事件处理器和事件过滤器是怎么使用的. 事件处理器 ...
- 对QT中QBitArray类进行简单剖析
我们知道Qt中的QBitArray类支持在位(bit)的层次上进行数据操作.本文剖析该类在二进制文件读写时的一些要点.另外,在Qt中,QDataStream类对于二进制文件的读写提供了诸多便利,需要注 ...
随机推荐
- 如何让iframe背景色透明框架页文件设置
如何让iframe背景色透明框架页文件设置:<body style="background-color:transparent" > 或 <body bgColo ...
- vuecli的使用之项目中的文件
cli创建的项目截图 node_moudule :下载的依赖包的存储位置. public :html的地方??? src :写代码的地方 man.js :入口文件 .browserslistrc :浏 ...
- c/s结构的自动化——pyautogui
环境:Python 3.5.3 pip install pyautogui -i http://pypi.douban.com/simple --trusted-host pypi.douban.co ...
- 服务器搭建域控与SQL Server的AlwaysOn环境过程(一) 搭建域控服务器
0 准备阶段 1. Windows Server 服务器 3台(其中域控服务器配置可降低一个水准,目前博主试用的是:域控服务器--2核4G 数据库服务器(节点)--4核8G ) 2. SQL Serv ...
- String值传递剖析
转载自 http://www.iteye.com/topic/412531 提要:本文从实现原理的角度上阐述和剖析了:在Java语言中,以String作为类型的变量在作为方法参数时所表现出的“非对象” ...
- Linux快速入门打开你的学习之道
Linux快速入门打开你的学习之道 相信看到这篇文章的你一定是想要学习Linux,或者已经在学习Linux的人了,那我们就可以一起探讨一下,学习Linux如何快速入门呢? 首先,希望大家弄清楚自己为什 ...
- 题解 P3834 【【模板】可持久化线段树 1(主席树)】
可持久化线段树的前置知识是权值线段树,但是你不学也没有太大的关系因为思想不是很难理解. 可持久化线段树支持历史记录查询,这是它赖以解题的方法. 在本题中思路是建立n颗线段树,然后对于每次询问,考虑其中 ...
- Apache activemq入门示例(maven项目)
http://outofmemory.cn/java/mq/apache-activemq-demo
- 【剑指Offer学习】【面试题47:不用加减乘除做加法】
题目:写一个函数,求两个整数之和,要求在函数体内不得使用+.-.×.÷四则运算符号. 解题思路 5 的二进制是101, 17 的二进制是10001 .还是试着把计算分成三步:第一步各位相加但不计进位. ...
- springboot actuator shutdown正确的关闭操作
今天整合ehcache时发现一个很重要的问题,就是程序关闭(硬关闭)之后,持久化到磁盘的缓存数据没能正确写入加载,问题还是硬关闭的问题,所以就使用actuator 进行监听 <dependenc ...