我们在新建一个Qt GUI项目时,main函数里会生成类似下面的代码:

int main(int argc, char *argv[])
{
QApplication application(argc, argv);
CQDialog dialog(NULL);
dialog.show();
return application.exec();
}

对应的步骤解释如下

1.构建QApplication对象

2.构建CQDialog主界面

3.主界面显示

4.QApplication对象进入事件循环处理直至退出

上述步骤包含QApplication对象构建过程、主界面显示过程、事件循环处理过程三个主题。

这篇博文主要讲解第一个主题,即QApplication对象构建过程。

QApplication类继承关系如下图所示

查看Qt源码QApplication的构造函数

#ifdef Q_QDOC
QApplication::QApplication(int &argc, char **argv)
#else
QApplication::QApplication(int &argc, char **argv, int _internal)
#endif
: QGuiApplication(*new QApplicationPrivate(argc, argv, _internal))
{
Q_D(QApplication);
d->init();
}

QApplication父类QGuiApplication的构造函数

QGuiApplication::QGuiApplication(QGuiApplicationPrivate &p)
: QCoreApplication(p)
{
}

可以看到QGuiApplication的构造函数为空内容,进入到QGuiApplication父类QCoreApplication的构造函数

QCoreApplication::QCoreApplication(QCoreApplicationPrivate &p)
#ifdef QT_NO_QOBJECT
: d_ptr(&p)
#else
: QObject(p, 0)
#endif
{
d_func()->q_ptr = this;
// note: it is the subclasses' job to call
// QCoreApplicationPrivate::eventDispatcher->startingUp();
}

其也没有实际性的内容。

主要集中在QApplicationPrivateQGuiApplicationPrivateQCoreApplicationPrivate类的内部处理,这也是Qt一贯的用法,即信息隐藏。

其类关系图如下

因此函数调用返回到QApplication构造函数中,QApplicationPrivate::init函数被调用用于初始化操作

void QApplicationPrivate::init()
{
#if defined(Q_OS_MACOS)
QMacAutoReleasePool pool;
#endif QGuiApplicationPrivate::init(); initResources(); qt_is_gui_used = (application_type != QApplicationPrivate::Tty);
process_cmdline(); // Must be called before initialize()
qt_init(this, application_type);
initialize();
eventDispatcher->startingUp(); #ifdef QT_EVAL
extern void qt_gui_eval_init(QCoreApplicationPrivate::Type);
qt_gui_eval_init(application_type);
#endif
#ifndef QT_NO_ACCESSIBILITY
// factory for accessible interfaces for widgets shipped with Qt
QAccessible::installFactory(&qAccessibleFactory);
#endif }

QGuiApplicationPrivate::init会调用QCoreApplicationPrivate::initQCoreApplicationPrivate::init会进行eventDispatcher的创建,如下代码所示

#ifndef QT_NO_QOBJECT
// use the event dispatcher created by the app programmer (if any)
if (!eventDispatcher)
eventDispatcher = threadData->eventDispatcher.load();
// otherwise we create one
if (!eventDispatcher)
createEventDispatcher();
Q_ASSERT(eventDispatcher); if (!eventDispatcher->parent()) {
eventDispatcher->moveToThread(threadData->thread);
eventDispatcher->setParent(q);
} threadData->eventDispatcher = eventDispatcher;
eventDispatcherReady();
#endif

基于多态性,QGuiApplicationPrivate::createEventDispatcher被调用

void QGuiApplicationPrivate::createEventDispatcher()
{
Q_ASSERT(!eventDispatcher); if (platform_integration == 0)
createPlatformIntegration(); // The platform integration should not mess with the event dispatcher
Q_ASSERT(!eventDispatcher); eventDispatcher = platform_integration->createEventDispatcher();
}

createEventDispatcher函数里做两件事情

1.创建平台插件(Windows、Linux)

2.根据平台插件创建eventDispatcher

以我在Windows平台上开发为例

1.创建QWindowsIntegration以及QWindowsGuiEventDispatcher

2.在QWindowsIntegration创建过程中会生成QWindowsContext对象

QEventDispatcherWin32类继承关系如下图所示

因此,QApplication构造时创建了eventDispatcher

关于QApplication对象构建过程就讲述完毕了,后续博文会看到eventDispatcher、QWindowsContext的用途

有部分代码位于qtbase\src\plugins\platforms源码目录

Qt事件分发机制源码分析之QApplication对象构建过程的更多相关文章

  1. Android事件分发机制源码分析

    Android事件分发机制源码分析 Android事件分发机制源码分析 Part1事件来源以及传递顺序 Activity分发事件源码 PhoneWindow分发事件源码 小结 Part2ViewGro ...

  2. Android查缺补漏(View篇)--事件分发机制源码分析

    在上一篇博文中分析了事件分发的流程及规则,本篇会从源码的角度更进一步理解事件分发机制的原理,如果对事件分发规则还不太清楚的童鞋,建议先看一下上一篇博文 <Android查缺补漏(View篇)-- ...

  3. Android View事件分发-从源码分析

    View事件分发-从源码分析 学习自 <Android开发艺术探索> https://blog.csdn.net/qian520ao/article/details/78555397?lo ...

  4. Android View 事件分发机制 源码解析 (上)

    一直想写事件分发机制的文章,不管咋样,也得自己研究下事件分发的源码,写出心得~ 首先我们先写个简单的例子来测试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个My ...

  5. ApplicationEvent事件机制源码分析

    <spring扩展点之三:Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法,在spring启动后做些事情> <服务网关zu ...

  6. Qt update刷新之源码分析(一)

    在做GUI开发时,要让控件刷新,会调用update函数:那么在调用了update函数后,Qt究竟基于什么原理.执行了什么代码使得屏幕上有变化?本文就带大家来探究探究其内部源码. Qt手册中关于QWid ...

  7. Springboot学习04-默认错误页面加载机制源码分析

    Springboot学习04-默认错误页面加载机制源码分析 前沿 希望通过本文的学习,对错误页面的加载机制有这更神的理解 正文 1-Springboot错误页面展示 2-Springboot默认错误处 ...

  8. Envoy 源码分析--程序启动过程

    目录 Envoy 源码分析--程序启动过程 初始化 main 入口 MainCommon 初始化 服务 InstanceImpl 初始化 启动 main 启动入口 服务启动流程 LDS 服务启动流程 ...

  9. SpringBoot源码分析之SpringBoot的启动过程

    SpringBoot源码分析之SpringBoot的启动过程 发表于 2017-04-30   |   分类于 springboot  |   0 Comments  |   阅读次数 SpringB ...

随机推荐

  1. 跑酷天堂C++小黑框版

    上:跳跃 左右:行走 #include <bits/stdc++.h> #include <windows.h> #include <conio.h> using ...

  2. 1、Hibernate-入门

    一.概述 1.什么是Hibernate: Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,h ...

  3. [springboot 开发单体web shop] 5. 用户登录及首页展示

    用户登录及前端展示 用户登录 在之前的文章中我们实现了用户注册和验证功能,接下来我们继续实现它的登录,以及登录成功之后要在页面上显示的信息. 接下来,我们来编写代码. 实现service 在com.l ...

  4. 《吊打面试官》系列-Redis常见面试题(带答案)

    你知道的越多,你不知道的越多 点赞再看,养成习惯 GitHub上已经开源,有面试点思维导图,欢迎[Star]和[完善] 前言 Redis在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在 ...

  5. python入门递归之阶乘

    def recurursion(n): if n == 1: return 1 else: return n * recurursion(n-1) number = int(input("请 ...

  6. nginx跨域解决方案

    nginx跨域解决方案Access to Font at 'http://47.104.86.187/yinjiatoupiao2/iconfont/iconfont.woff' from origi ...

  7. redis 数据库主从不一致问题解决方案

     在聊数据库与缓存一致性问题之前,先聊聊数据库主库与从库的一致性问题. 问:常见的数据库集群架构如何? 答:一主多从,主从同步,读写分离. 如上图: (1)一个主库提供写服务 (2)多个从库提供读服务 ...

  8. 解决mybatis中 数据库column 和 类的属性名property 不一致的两种方式

    解决方式way1:resultMap (1)studentMapper.xml <!-- 当数据库的字段名 和 类的属性名 不一致的时候的解决方式:2种 way1--> <selec ...

  9. volatile相关内容

    volatile是jvm提供的轻量级的同步机制 保证可见性(一个线程的修改对其它线程是可见的) 不保证原子性 禁止指令重排序 什么是指令重排? 计算机在执行程序时,为了提高性能,编译器和处理器会对指令 ...

  10. VsCode Python配置安装教程

    1.软件下载地址 Python官网: https://www.python.org/downloads/windows/ Python下载地址: https://www.python.org/ftp/ ...