Qt项目文件以及对象树

"在哪里走散,你都会找到我~"


前篇,我们仅仅对Qt创建了第一个简单的项目。相比于使用其他IDE创建工程项目,Qt会为自动创建诸如:.pro、.h\.cpp、.iu等文件,这些文件到底是什么?我们在使用Qt时 应该怎样去看待?

------前言

Qt项目文件解析

(1) .pro文件

当我们将工程文件创建好了之后,在⼯程⽬录列表中有⼀个后缀为".pro" 的⽂件,这个".pro"文件就是工程文件。它是由qmake自动产生的,用于生产makefile配置的文件。

什么是makefile?

一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。

makefile在Linux中使用得较为频繁,其工作目的就是完成源文件编译。在Qt Creator中已经把整个过程中的编译细节封装好了,对于使用者的我们来说,不用在意里面的内容:

(2) widget \main.cpp ⽂件解析

当我们使用Qt Creator创建项目时,会自动为我们写好完整调用的main函数。

在Qt中,着重强调类的封装。Qt ⼀个类对应⼀个头⽂件,类名 就是 头⽂件名。

QApplication 为应⽤程序类:
要想编写一个Qt的图形化界面程序,必须要有一个QApplication对象。

除此之外,还会为我们创建在新建项目时,选择的"Widget":

这里提到了两个概念,一个是"Q_OBJECT",另一个是"对象树"。

Q_OBJECT宏:

这是一个Qt内置的一个宏。当代码被替换展开后,就是一堆代码块。Qt中一个很重要的机制就是"信号和槽"。如果想要使用这一个机制,就必须包含这个宏。

对象树:

Qt中引入了"对象树"机制。这个树到底是做什么的呢?我们在这里就把它简单地认为是一个对象资源管理的机制。当我们创建一个Qt对象,就可以将它挂在对象树上,由它来控制这个资源的释放销毁。似乎同"垃圾回收"机制类似,但它对性能的影响很小。

(3) widget.ui ⽂件解析

当我们点击这个文件时,Qt Creator会为我们Qt Design上:

当我们再次返回到编辑,点击这个.ui文件时,就会变成这样:

如果你了解过前端,那么你看到这样神似的代码,似乎会联想到".html"。不过,虽然它们极其相似,但.ui文件是由"xml"格式输写的。

在xml中,有哪些标签,表示什么含义都是通过程序员自定义的。此处的xml中的标签,就是大佬们开发的专属Qt的标签。至于每个标签是啥含义呢,并不需要我们去关心,我们只需要知道.ui文件本质上是一个xml格式的文件即可。

当我们对当前.ui文件进行编译,打开左上方项目的"展开Expoler":
找到同层目录下的新目录。这些以"build-xx"开头的新目录,这是我们将Qt程序启动后,自动生成的临时文件:
我们打开ui文件:
所以,ui文件的本质,最终会被Qt Creator翻译成C++文件,并编译到可执行程序之中。

其中,我们还能看到由qmake自动生成的makefile。


Qt对象树

在 Qt 中创建很多对象的时候会提供⼀个 Parent 对象指针,这些Parent指针都需要被进行构造,可是,为什么需要构造这些Parent指针呢?

对于C\C++ 程序员而言,该语言为了追求性能,并没有提供类似"垃圾回收"的机制。所以,当使用程序申请堆上空间、或者是文件描述符、套接字等系统资源,需要由程序员手动回收。可是!只要是人工操作,就可能失误,就会出现申请的资源不能得到及时释放,从而让系统内的资源被占用,系统剩余资源越来越少,导致机器变卡甚至宕机......上述的种种,换句话说,也就是"资源泄露"。

(1) QObject

在Qt中,QObject是对象模型的核心。它是以"对象树"的形式组织起来的。

🥪 当创建一个QObject对象时,会看到 QObject 的构造函数接收⼀个 QObject 指针作为参数,这个参数就是 parent,也就是⽗对象指针。

🥪 这相当于,在创建 QObject 对象时,可以提供⼀个其⽗对象,我们创建的这个 QObject 对象会⾃动添加到其⽗对象的 children() 列表。

🥪 当⽗对象析构的时候,这个列表中的所有对象也会被析构。

如何理解QWidget 是能够在屏幕上显⽰的⼀切组件的⽗类?

QWidget 继承自QObject。当然不止QWidget,几乎所有的类对象都会去继承这个QObject。也是因为这种继承,也继承了这种对象树的关系。

使用对象树,把这些内容组织起来,等到合适的时机(窗口关闭\进程结束等等),把这些对象统一进行释放。

• Qt 引⼊对象树的概念,在⼀定程度上解决了内存问题。

释放规则:

🌯 当⼀个 QObject 对象在堆上创建的时候,Qt 会同时为其创建⼀个对象树,而对象树中对象的
顺序是没有定义的。
🌯 任何对象树中的 QObject 对象 delete 的时候,如果这个对象有 parent,则⾃动将其从 parent 的 children() 列表中删除;如果有孩⼦,则⾃动 delete 每⼀个孩⼦。

(2) 自定义类挂对象树

比如现如今,我们想要我们自定义的类MyLabel,继承QLabel,并尝试将其挂在对象树上:


Qt 窗⼝坐标体系 与 日志输出

坐标体系:以左上⻆为原点(0,0),X向右增加,Y向下增加。其中(0,0)坐标的位置指的是Widget对象的左上角。

我们在.ui文件中,能看到的"画板",其本质上就是QWidget窗口:

我们在这个窗口中添加一个"按钮Button":

我们还可以通过代码的方式,创建一个Button,并把它显示在最终程序运行的窗口上:

编码问题:

现在,我们想使用std::cout 作为日志输出打印在Qt Creator中的观察台中:

我们会发现,从屏幕输出的文字完完全全是乱码!

关于乱码的问题,有且仅有一个原因,就是编码方式不匹配!目前汉字字符集最常见的两种方式就是:UTF-8(utf8) 和 GBK。我们Windows简体中文版自带的就是按照GBK的编码方式,对汉字进行翻译的。相反Linux中,使用的汉字编码集为utf8。

GBK. 使用两个字节表示一个汉字。

UTF-8/utf8 变长编码。表示一个符号,使用的字节数有变化,2~4。但汉字一般又3个字节表示。

因此,在Qt中如果想要通过打印日志的方式,观察程序、调试信息,最好使用Qt提供的qDebug。虽然cout也不是不能用,但是std::cout内部不会对编码作任何处理,在持有不同编码集中使用,会导致乱码;

相关推荐
只待花开1 小时前
QT5.12.9 通过MinGW64 / MinGW32 cmake编译Opencv4.5.1
开发语言·qt
代码小狗Codog1 小时前
C++ Qt 自制开源科学计算器
c++·qt
我写代码菜如坤1 小时前
C#中Stopwatch的使用
开发语言·c#
wjs20242 小时前
SQLite Glob 子句
开发语言
MarkHD5 小时前
javascript 常见设计模式
开发语言·javascript·设计模式
海盗猫鸥6 小时前
C++入门基础篇(1)
开发语言·c++·学习
专注成就自我6 小时前
java使用easypoi模版导出word详细步骤
java·开发语言·word
多多*6 小时前
SpringBoot 启动流程六
java·开发语言·spring boot·后端·spring
让你三行代码QAQ6 小时前
SpringSecurity初始化过程
java·开发语言
Mr_Richard7 小时前
Java动态代理的实现方式
java·开发语言