Qt中事件分发源代码剖析(一共8个步骤,顺序非常清楚:全局的事件过滤器,再传递给目标对象的事件过滤器,最终传递给目标对象)
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 <span style="color:#ff6666;">QGuiApplication::exec();</span>
- }
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 :<span style="color:#ff6666;"> d->notify_helper</span>(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步的代码可以看出事件传递
传递的顺序是:首先传递给全局的事件过滤器,再传递给目标对象的事件过滤器,最终传递给目标对象。
http://blog.csdn.net/chenlong12580/article/details/25009095
Qt中事件分发源代码剖析(一共8个步骤,顺序非常清楚:全局的事件过滤器,再传递给目标对象的事件过滤器,最终传递给目标对象)的更多相关文章
- Qt中事件分发源代码剖析
Qt中事件分发源代码剖析 Qt中事件传递顺序: 在一个应该程序中,会进入一个事件循环,接受系统产生的事件,并且进行分发,这些都是在exec中进行的. 下面举例说明: 1)首先看看下面一段示例代码: i ...
- Qt中事件分发源码剖析
Qt中事件分发源码剖析 Qt中事件传递顺序: 在一个应该程序中,会进入一个事件循环,接受系统产生的事件,而且进行分发,这些都是在exec中进行的. 以下举例说明: 1)首先看看以下一段演示样例代码: ...
- 关于JAVA中事件分发和监听机制实现的代码实例-绝对原创实用
http://blog.csdn.net/5iasp/article/details/37054171 文章标题:关于JAVA中事件分发和监听机制实现的代码实例 文章地址: http://blog.c ...
- Android与javascript中事件分发机制的简单比较
在前面两篇博客中,我们讨论了Android中的事件分发的相关内容,那么在本篇博客当中,我们就简单探讨一下html或javascript中的事件分发机制,并进行简单的对比. 在前端中,对事件进行绑定有三 ...
- QT中事件处理器和事件过滤器实现实例
Qt中事件处理的方式,最常用的就是使用事件处理器(event handler)和事件过滤器(event filter)这两种方法.接下来,我们就来看看事件处理器和事件过滤器是怎么使用的. 事件处理器 ...
- JDK1.7中的ThreadPoolExecutor源代码剖析
JDK1. 7中的ThreadPoolExecutor 线程池,顾名思义一个线程的池子,池子里存放了非常多能够复用的线程,假设不用线程池相似的容器,每当我们须要创建新的线程时都须要去new Threa ...
- Qt 中事件与处理
一.事件与处理程序在运算过程中发生的一些事情:鼠标单击.键盘的按下...这些的事件的监控与处理在Qt中不是以信号的方式处理的.当这些事件发生时会调用QObject类中的功能函数(虚函数),所有的控件类 ...
- Android事件分发机制浅谈(二)--源码分析(ViewGroup篇)
上节我们大致了解了事件分发机制的内容,大概流程,这一节来分析下事件分发的源代码. 我们先来分析ViewGroup中dispatchTouchEvent()中的源码 public boolean dis ...
- 第39课 Qt中的事件处理(下)
1. 事件的传递过程 (1)操作系统检测到用户动作时,会产生一条系统消息,该消息被发送到Qt应用程序 (2)Qt应用程序收到系统消息后,将其转化为一个对应的QEvent事件对象,并调用QObject: ...
随机推荐
- Mysql 插入记录时检查记录是否已经存在,存在则更新,不存在则插入记录SQL
我们在开发数据库相关的逻辑过程中, 经常检查表中是否已经存在这样的一条记录, 如果存在则更新或者不做操作, 如果没有存在记录,则需要插入一条新的记录. 这样的逻辑固然可以通过两条sql语句完成. SE ...
- [jumping to the gate] 娱乐向setjmp
转载:http://tieba.baidu.com/p/1393753521 灌水的时候从goto一路拐到了setjmp, 顺便也试了试貌似这东西确实是没有析构效果的.之前并没有看过setjmp的实现 ...
- C++按值和按址传递对象的思考和优化
C++是一门面向对象(OOP)编程语言,在这门语言中也有函数,函数的参数可以是变量数值,当然也可以是对象.所以,传统地就有关于对象是按值传递还是按址传递的讨论. 在C语言中,按值传递在很多情况下可以出 ...
- PHP连接sql server 2005环境配置
一.Windows下PHP连接SQLServer 2005 设定:安装的Windows操作系统(Win7 或XP均可.其它系统暂未測试),在C盘下:PHP的相关文件位于c:/PHP以下,其配置文件ph ...
- Atitit. 最佳实践 QA----减少cpu占有率--cpu占用太高怎么办
Atitit. 最佳实践 QA----减少cpu占有率--cpu占用太高怎么办 跟个磁盘队列长度雅十,一到李80%走不行兰.... 1. 寻找线程too 多的.关闭... Taskman>> ...
- 【软件技巧】Sublime Text为不同语法定义不同高亮
Sublime Text默认的语法高亮已经非常美丽了,可是对于个别语言还是有些不爽. 默认高亮规则叫Monokai,能够从Preferences->Settings - Default中看到: ...
- JQuery hover(over,out) 使用笔记
转载自:http://www.douban.com/note/202404884/ JQuery hover(over,out) 使用笔记 JavaScript 下.onmouseover() 和 o ...
- WEB服务器2--IIS架构(转)
开始之前可以先读:http://www.cnblogs.com/tiantianle/p/5419445.html 原文:http://www.cnblogs.com/arbin98/archive/ ...
- ASP.NET内核几大对象、ASP.NET核心知识(6)--转载
这篇博文主要介绍一下几个对象. 1)HttpContext 2)HttpRequest 3)HttpResponse 4)context. Server 5)context.Session HttpC ...
- EF搭建可扩展菜单
EF实现可扩展性菜单 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !impo ...