我们在新建一个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. NIO 在Tomcat中的应用

    对NIO的理解 个人单方面认为,NIO与BIO的最大区别在于主动和被动,使用BIO的方式需要等待被调用方返回数据,很明显此时调用者是被动的. 举个例子 阻塞IO 假设你是一个胆小又害羞的男孩子,你约了 ...

  2. [开源]基于goapp+xterm实现webssh-网页上的SSH终端(golang)

    简析 基于goapp+xterm实现webssh-网页上的SSH终端. 开源地址见文末. 特性 在网页上实现一个SSH终端.从而无需Xshell之类的模拟终端工具进行SSH连接. 可以对交互命令进行审 ...

  3. 模拟80(a)

    其实隔壁的那套题比这套难的多....一道都不会.. T1 题目中已经给出了递推公式,那么这题就没什么了,直接矩阵乘就完了. 然而考场上并没有看出矩阵,主要是用了好久发明crt,我知道原理,但是不会打了 ...

  4. CSPS模拟 51

    蒟蒻由于仍然苟活在$1jf$,不得不接受省选题的吊打$QWQ$ 蒟蒻由于拿了大神们不屑打的弱智暴力,而大神们$T3$的各种快速变换没调出来,所以拿到辽人生第一个$1jf$黄名 既侥幸又$kx$ T1 ...

  5. 『题解』洛谷P4016 负载平衡问题

    title: categories: tags: - mathjax: true --- Problem Portal Portal1:Luogu Portal2: LibreOJ Descripti ...

  6. docker——harbor

    为什么要用harbor? 在实际生产运维中,往往需要把镜像发布到几十.上百台或更多的节点上.这时单台Docker主机上镜像已无法满足,项目越来越多,镜像就越来越多,都放到一台Docker主机上是不行的 ...

  7. 2、Linux基础练习题

    题目 答案 1.答案 [root@centos7 ~]# date +'%F %T' 2019-07-23 10:21:35 2.答案 [root@centos7 ~]# date +%A -d '- ...

  8. VsCode Python配置安装教程

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

  9. T-SQL Part VIII: CROSS APPLY, OUTER APPLY

    除了CROSS JOIN, INNER JOIN, OUTER JOIN之外,T-SQL还提供了CROSS APPLY和OUTER APPLY这两个较为另类的Set操作符. 首先来看CROSS APP ...

  10. 你不知道的JS系列【1】- 什么是作用域

      几乎所有的编程语言都能够储存变量,并且能在之后对这个变量值进行访问或修改,正是储存和访问变量的能力将状态带给了程序,那么,这些变量储存在哪里呢?程序需要时又是如何找到他们?这些问题说明需要一套设计 ...