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内部不会对编码作任何处理,在持有不同编码集中使用,会导致乱码;

相关推荐
用户805533698031 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner1 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz6 天前
QML Hello World 入门示例
qt
xcyxiner9 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner10 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner10 天前
DicomViewer (添加模型类)3
qt
xcyxiner11 天前
DicomViewer (目录调整) 2
qt
xcyxiner11 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00613 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术13 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript