Qt中事件分发源代码剖析

Qt中事件传递顺序:

在一个应该程序中,会进入一个事件循环,接受系统产生的事件,并且进行分发,这些都是在exec中进行的。
下面举例说明:

1)首先看看下面一段示例代码:

  1. int main(int argc, char *argv[])
  2. {
  3. QApplication a(argc, argv);
  4. MouseEvent w;
  5. w.show();
  6. return a.exec();
  7. }

2)a.exec进入事件循环,调用的是QApplication::exec();

  1. int QApplication::exec()
  2. {
  3. return <span style="color:#ff6666;">QGuiApplication::exec();</span>
  4. }

3)QApplication::exec()调用的是QGuiApplication::exec();

  1. int QGuiApplication::exec()
  2. {
  3. #ifndef QT_NO_ACCESSIBILITY
  4. QAccessible::setRootObject(qApp);
  5. #endif
  6. return QCoreApplication::exec();
  7. }

4)QGuiApplication::exec()调用的是QCoreApplication::exec();

  1. int QCoreApplication::exec()
  2. {
  3. if (!QCoreApplicationPrivate::checkInstance("exec"))
  4. return -1;
  5. QThreadData *threadData = self->d_func()->threadData;
  6. if (threadData != QThreadData::current()) {
  7. qWarning("%s::exec: Must be called from the main thread", self->metaObject()->className());
  8. return -1;
  9. }
  10. if (!threadData->eventLoops.isEmpty()) {
  11. qWarning("QCoreApplication::exec: The event loop is already running");
  12. return -1;
  13. }
  14. threadData->quitNow = false;
  15. QEventLoop eventLoop;
  16. self->d_func()->in_exec = true;
  17. self->d_func()->aboutToQuitEmitted = false;
  18. int returnCode = eventLoop.exec();
  19. threadData->quitNow = false;
  20. if (self) {
  21. self->d_func()->in_exec = false;
  22. if (!self->d_func()->aboutToQuitEmitted)
  23. emit self->aboutToQuit(QPrivateSignal());
  24. self->d_func()->aboutToQuitEmitted = true;
  25. sendPostedEvents(0, QEvent::DeferredDelete);
  26. }
  27. return returnCode;
  28. }

5)QCoreApplication::exec()调用eventLoop.exec()进行事件循环;

  1. int QEventLoop::exec(ProcessEventsFlags flags)
  2. {
  3. Q_D(QEventLoop);
  4. //we need to protect from race condition with QThread::exit
  5. QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread))->mutex);
  6. if (d->threadData->quitNow)
  7. return -1;
  8. if (d->inExec) {
  9. qWarning("QEventLoop::exec: instance %p has already called exec()", this);
  10. return -1;
  11. }
  12. struct LoopReference {
  13. QEventLoopPrivate *d;
  14. QMutexLocker &locker;
  15. bool exceptionCaught;
  16. LoopReference(QEventLoopPrivate *d, QMutexLocker &locker) : d(d), locker(locker), exceptionCaught(true)
  17. {
  18. d->inExec = true;
  19. d->exit = false;
  20. ++d->threadData->loopLevel;
  21. d->threadData->eventLoops.push(d->q_func());
  22. locker.unlock();
  23. }
  24. ~LoopReference()
  25. {
  26. if (exceptionCaught) {
  27. qWarning("Qt has caught an exception thrown from an event handler. Throwing\n"
  28. "exceptions from an event handler is not supported in Qt. You must\n"
  29. "reimplement QApplication::notify() and catch all exceptions there.\n");
  30. }
  31. locker.relock();
  32. QEventLoop *eventLoop = d->threadData->eventLoops.pop();
  33. Q_ASSERT_X(eventLoop == d->q_func(), "QEventLoop::exec()", "internal error");
  34. Q_UNUSED(eventLoop); // --release warning
  35. d->inExec = false;
  36. --d->threadData->loopLevel;
  37. }
  38. };
  39. LoopReference ref(d, locker);
  40. // remove posted quit events when entering a new event loop
  41. QCoreApplication *app = QCoreApplication::instance();
  42. if (app && app->thread() == thread())
  43. QCoreApplication::removePostedEvents(app, QEvent::Quit);
  44. while (!d->exit)
  45. processEvents(flags | WaitForMoreEvents | EventLoopExec);
  46. ref.exceptionCaught = false;
  47. return d->returnCode;
  48. }

6)eventLoop.exec()调用QCoreApplication的processEvents进行事件分发;

7)调用notify进行分发

QCoreApplication::sendEvent、QCoreApplication::postEvent和QCoreApplication::sendPostedEvents都调用notify进行事件分发;

  1. bool QCoreApplication::notify(QObject *receiver, QEvent *event)
  2. {
  3. Q_D(QCoreApplication);
  4. // no events are delivered after ~QCoreApplication() has started
  5. if (QCoreApplicationPrivate::is_app_closing)
  6. return true;
  7. if (receiver == 0) {                        // serious error
  8. qWarning("QCoreApplication::notify: Unexpected null receiver");
  9. return true;
  10. }
  11. #ifndef QT_NO_DEBUG
  12. d->checkReceiverThread(receiver);
  13. #endif
  14. return receiver->isWidgetType() ? false :<span style="color:#ff6666;"> d->notify_helper</span>(receiver, event);
  15. }

8)notify调用notify_helper进行事件分发;

  1. bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)
  2. {
  3. // send to all application event filters
  4. if (sendThroughApplicationEventFilters(receiver, event))
  5. return true;
  6. // send to all receiver event filters
  7. if (sendThroughObjectEventFilters(receiver, event))
  8. return true;
  9. // deliver the event
  10. return receiver->event(event);
  11. }

9)从上面第8步的代码可以看出事件传递

传递的顺序是:首先传递给全局的事件过滤器,再传递给目标对象的事件过滤器,最终传递给目标对象。

http://blog.csdn.net/chenlong12580/article/details/25009095

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

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

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

  2. Qt中事件分发源码剖析

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

  3. 关于JAVA中事件分发和监听机制实现的代码实例-绝对原创实用

    http://blog.csdn.net/5iasp/article/details/37054171 文章标题:关于JAVA中事件分发和监听机制实现的代码实例 文章地址: http://blog.c ...

  4. Android与javascript中事件分发机制的简单比较

    在前面两篇博客中,我们讨论了Android中的事件分发的相关内容,那么在本篇博客当中,我们就简单探讨一下html或javascript中的事件分发机制,并进行简单的对比. 在前端中,对事件进行绑定有三 ...

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

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

  6. JDK1.7中的ThreadPoolExecutor源代码剖析

    JDK1. 7中的ThreadPoolExecutor 线程池,顾名思义一个线程的池子,池子里存放了非常多能够复用的线程,假设不用线程池相似的容器,每当我们须要创建新的线程时都须要去new Threa ...

  7. Qt 中事件与处理

    一.事件与处理程序在运算过程中发生的一些事情:鼠标单击.键盘的按下...这些的事件的监控与处理在Qt中不是以信号的方式处理的.当这些事件发生时会调用QObject类中的功能函数(虚函数),所有的控件类 ...

  8. Android事件分发机制浅谈(二)--源码分析(ViewGroup篇)

    上节我们大致了解了事件分发机制的内容,大概流程,这一节来分析下事件分发的源代码. 我们先来分析ViewGroup中dispatchTouchEvent()中的源码 public boolean dis ...

  9. 第39课 Qt中的事件处理(下)

    1. 事件的传递过程 (1)操作系统检测到用户动作时,会产生一条系统消息,该消息被发送到Qt应用程序 (2)Qt应用程序收到系统消息后,将其转化为一个对应的QEvent事件对象,并调用QObject: ...

随机推荐

  1. WPF笔记(2.8 常用的布局属性)——Layout

    原文:WPF笔记(2.8 常用的布局属性)--Layout 这一节老没意思,啰里啰唆的尽是些HTML的属性,挑几个好玩的List出来,备忘:Padding与Margin的区别:Margin指控件边界与 ...

  2. linux awk 使用

    awk是linux下的一个命令,他对其他命令的输出,对文件的处理都十分强大,其实他更像一门编程语言,他可以自定义变量,有条件语句,有循环,有数组,有正则,有函数等.他读取输出,或者文件的方式是一行,一 ...

  3. [置顶] Android EditText/TextView使用SpannableString显示复合文本

    在Android中EditText用于编辑文本,TextView用于显示文本,但是有时候我们需要对其中的文本进行样式等方面的设置.Android为我们提供了SpannableString类来对指定文本 ...

  4. [转]jQuery EasyUI 扩展-- 主题(Themes)

    主题(Themes)允许您改变站点的外观和感观.使用主题可以节省设计的时间,让您腾出更多的时间进行开发.您也可以创建一个已有主题的子主题. 主题生成器(Theme Builder) jQuery UI ...

  5. Android应用开发学习之Toast消息提示框

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz 本文我们来看Toast消息提示框的用法.使用Toast消息提示框一般有三个步骤: 1.  创建一个Toast对象.可 ...

  6. AsyncTask实现下载图片

    实现效果: /*采用异步任务  AsyncTask<String,Integer, byte[]>  * 参数一代表 执行异步任务时传递的参数的类型  * 参数二 如果不采用进度,则填Vo ...

  7. ubuntu14.04 安装 StudioZend12

    到官网下载:http://www.zend.com/en/products/studio/downloadsLinux-64位:http://downloads.zend.com/studio-ecl ...

  8. UIImageView圆角,自适应图片宽高比例,图片拉伸,缩放比例和图片缩微图

    /*      设置圆角,通过layer中的cornerRadius和masksToBounds即可.            自适应图片宽高比例.通过UIViewContentModeScaleAsp ...

  9. OSX: 私人定制Dock默认程序图标

    不论什么一个新用户第一次登陆后,OSX都会自己主动地在用户的Dock中列出系统默认的应用程序图标,这些图标随着OSX版本号的不同而不同. 系统管理员有的时候须要改变这些系统默认图标,或者加入自己的或者 ...

  10. Git 笔记二-Git安装与初始配置

    git 笔记二-Git安装与初始配置 Git的安装 由于我日常生活和工作基本上都是在Windows上,因此此处只说windows上的安装.Windows上的安装和其他程序一样,只需要到http://g ...