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中事件分发源码剖析的更多相关文章

  1. ViewGroup事件分发源码分析

    1.AndroidStudio源码调试方式 AndroidStudio默认是支持一部分源码调试的,但是build.gradle(app) 中的sdk版本要保持一致, 最好是编译版本.运行版本以及手机的 ...

  2. Android View事件分发源码分析

    引言 上一篇文章我们介绍了View的事件分发机制,今天我们从源码的角度来学习下事件分发机制. Activity对点击事件的分发过程 事件最先传递给当前Activity,由Activity的dispat ...

  3. android事件分发源码分析—笔记

    昨天晚上从源码角度复习了一下android的事件分发机制,今天将笔记整理下放在网上.其实说复习,也是按着<android开发艺术探索>这本书作者的思路做的笔记. 目录 事件是如何从Acti ...

  4. view事件分发源码理解

    有些困难无法逃避,没办法,那就只有去解决它.view事件分发对我而言是一块很难啃的骨头,看了<安卓开发艺术探索>关于这个知识点的讲解,看了好几遍,始终不懂,最终通过调试分析结果,看博客,再 ...

  5. Touch事件分发源码解析

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 以下源码基于Gingerbread 2.3.7 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1.先看ViewGroup的di ...

  6. Qt中事件分发源代码剖析(一共8个步骤,顺序非常清楚:全局的事件过滤器,再传递给目标对象的事件过滤器,最终传递给目标对象)

    Qt中事件分发源代码剖析 Qt中事件传递顺序: 在一个应该程序中,会进入一个事件循环,接受系统产生的事件,并且进行分发,这些都是在exec中进行的.下面举例说明: 1)首先看看下面一段示例代码: in ...

  7. Qt中事件分发源代码剖析

    Qt中事件分发源代码剖析 Qt中事件传递顺序: 在一个应该程序中,会进入一个事件循环,接受系统产生的事件,并且进行分发,这些都是在exec中进行的. 下面举例说明: 1)首先看看下面一段示例代码: i ...

  8. QT中事件处理器和事件过滤器实现实例

    Qt中事件处理的方式,最常用的就是使用事件处理器(event handler)和事件过滤器(event filter)这两种方法.接下来,我们就来看看事件处理器和事件过滤器是怎么使用的. 事件处理器 ...

  9. 对QT中QBitArray类进行简单剖析

    我们知道Qt中的QBitArray类支持在位(bit)的层次上进行数据操作.本文剖析该类在二进制文件读写时的一些要点.另外,在Qt中,QDataStream类对于二进制文件的读写提供了诸多便利,需要注 ...

随机推荐

  1. Hadoop2.x 关于日志文件位置

    查看日志是发现Hadoop问题和解决Hadoop问题的第一步. 开始我不知道该去哪找日志,后来我发现在我启动节点的时候,有打印信息以及明确告诉了日志写在哪. [root@master hadoop]# ...

  2. 12种CSS BUG解决方法与技巧

    一. 针对浏览器的选择器 这些选择器在你需要针对某款浏览器进行css设计时将非常有用. IE6及其更低版本,本文由52CSS.com整理,转载请注明出处! * html {} IE7及其更低版本 *: ...

  3. (2016北京集训十三)【xsy1533】mushroom - bitset

    题解: 神题...我看到的时候直接吓懵了... 这是一道STL题...否则可能要写可持久化ETT或者可持久化Toptree? 用bitset来维护每个蘑菇上哪里有杂草,那么 对于操作1和操作2:可以预 ...

  4. php xml 的基本操作类

    class xmlMessage{ protected $doc; protected $rootKey; public function __construct() { $this->doc ...

  5. 洛谷 P1169 [ZJOI2007]棋盘制作 (悬线法)

    和玉蟾宫很像,条件改成不相等就行了. 悬线法题目 洛谷 P1169  p4147  p2701  p1387 #include<cstdio> #include<algorithm& ...

  6. Jquery-基础知识点

    jquery 包含的功能 1.HTML元素选取.操作 2.CSS操作 3.HTML事件函数 4.Javascript特效和动画 5.HTML DOM遍历和修改 6.AJAX 7. Untilities ...

  7. 洛谷 P2209 [USACO13OPEN]燃油经济性Fuel Economy

    P2209 [USACO13OPEN]燃油经济性Fuel Economy 题目描述 Farmer John has decided to take a cross-country vacation. ...

  8. jeesite 简介

    jeesite 简介 https://github.com/thinkgem/jeesite http://jeesite.com/

  9. cocos2d-x-3.2 怎样创建新project

    1.在cocos2d-x-3.2\执行python命令 python setup.py //它的作用是将以下这些路径加入到你的用户环境变量中,当然你也能够不加入 COCOS_CONSOLE_ROOT ...

  10. 智课雅思短语---四、Exploit to the full one’s favorableconditions and avoid unfavorable ones

    智课雅思短语---四.Exploit to the full one’s favorableconditions and avoid unfavorable ones 一.总结 一句话总结:扬长避短 ...