【Qt】初识(上)

目录

[一、使用qt实现hello world](#一、使用qt实现hello world)

[1.1 图形化方式](#1.1 图形化方式)

[1.2 纯代码构建](#1.2 纯代码构建)

​编辑

二、对象树

三、乱码问题

四、小结

一、使用qt实现hello world

1.1 图形化方式

双击widget.ui 文件

拖拽控件至ui 界面窗口并修改内容;

构建并运行,效果如下所示:

然后我们进入explore到文件管理器里面查看下面这个文件直接拖拽到qt里面。

1.2 纯代码构建

我们先进入widge.cpp文件中。

构建运行就行,只不过是在左上角。

但是我们这里有一个问题,这里我们new了一个对象之后,没有进行delete?这样难道不会出现内存泄漏吗?

关注内存泄漏,是要融入DNA里面的。

内存泄漏是一个非常可怕,非常严重的事情!!

这种问题不容易第一时间发现。

上述代码,在qt中不会产生内存泄漏。

label对象会合适的时候被析构释放~~(虽然没有写,但是确实能释放)

之所以能够把对象释放掉,主要是因为把这个对象挂载到了对象树上面。

二、对象树

在Qt 中创建很多对象的时候会提供⼀个Parent 对象指针,下⾯来解释这个parent 到底是⼲什么的。

• QObject 是以对象树的形怯组织起来的。

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

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

o 当⽗对象析构的时候,这个列表中的所有对象也会被析构。(注意,这⾥的⽗对象并不是继承意义上的⽗类!)

这种机制在GUI 程序设计中相当有⽤。例如,⼀个按钮有⼀个QShortcut(快捷键)对象作为其⼦对象。当删除按钮的时候,这个快捷键理应被删除。这是合理的。

• QWidget 是能够在屏幕上显⽰的⼀切组件的⽗类。

o QWidget 继承⾃QObject,因此也继承了这种对象树关系。⼀个孩⼦⾃动地成为⽗组件的⼀个⼦组件。因此,它会显⽰在⽗组件的坐标系统中,被⽗组件的边界剪裁。例如,当⽤户关闭⼀个对话框的时候,应⽤程序将其删除,那么,我们希望属于这个对话框的按钮、图标等应该⼀起被删除。事实就是如此,因为这些都是对话框的⼦组件。

o 当然,我们也可以⾃⼰删除⼦对象,它们会⾃动从其⽗对象列表中删除。⽐如,当我们删除了⼀个⼯具栏时,其所在的主窗⼝会⾃动将该⼯具栏从其⼦对象列表中删除,并且⾃动调整屏幕显⽰。

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

• 当⼀个QObject 对象在堆上创建的时候,Qt 会同时为其创建⼀个对象树。不过,对象树中对象的顺序是没有定义的。这意味着,销毁这些对象的顺序也是未定义的。

• 任何对象树中的QObject 对象delete 的时候,如果这个对象有parent,则⾃动将其从parent 的 children()列表中删除;如果有孩⼦,则⾃动delete 每⼀个孩⼦。Qt 保证没有QObject 会被 delete 两次,这是由析构顺序决定的。

如果QObject 在栈上创建,Qt 保持同样的⾏为。正常情况下,这也不会发⽣什么问题。来看下⾯的代码⽚段:

作为⽗组件的window 和作为⼦组件的quit 都是QObject 的⼦类(事实上,它们都是QWidget的⼦类,⽽QWidget 是QObject 的⼦类)。这段代码是正确的,quit 的析构函数不会被调⽤两次,因为标准C++要求,局部对象的析构顺序应该按照其创建顺序的相反过程。因此,这段代码在超出作⽤域时,会先调⽤quit 的析构函数,将其从⽗对象window 的⼦对象列表中删除,然后才会再调⽤ window 的析构函数。

但是,如果我们使⽤下⾯的代码:

情况⼜有所不同,析构顺序就有了问题。我们看到,在上⾯的代码中,作为⽗对象的window 会⾸先被析构,因为它是最后⼀个创建的对象。在析构过程中,它会调⽤⼦对象列表中每⼀个对象的析构函数,也就是说,quit 此时就被析构了。然后,代码继续执⾏,在window 析构之后,quit 也会被析构,因为quit 也是⼀个局部变量,在超出作⽤域的时候当然也需要析构。但是,这时候已经是第⼆次调⽤quit 的析构函数了,C++不允许调⽤两次析构函数,因此,程序崩溃了。

由此我们看到,Qt 的对象树机制虽然在⼀定程度上解决了内存问题,但是也引⼊了⼀些值得注意的事情。这些细节在今后的开发过程中很可能时不时跳出来烦扰⼀下,所以,我们最好从开始就养成良好习惯

💡 在 Qt 中,尽量在构造的时候就指定 parent 对象,并且⼤胆在堆上创建。

Qt对象树如图:

对象树大概:

啥也没有。

这里我们新建一个文件,选择cpp,和cpp类。

需要我们手动包头文件。

成功构建了,但是日志有点问题。

三、乱码问题

为什么会出现乱码呢?

字符 编码/解码 - 锤子在线工具

挺好的无广告,纯净。

如何查看编码格式呢?点击explore

日志正常了。

四、小结

1、认识QLebal类,能够在界面上面显示字符串。

通过setText来设置的。参数QString(Qt中把cpp里面很多容器,进行了重新封装,历史原因)。

2、内存泄漏/文件资源泄漏

3、对象树。Qt中通过对象树,来统一的释放界面的控件对象。

Qt还是推荐使用new的方式在堆上创建对象,通过对象树,统一释放对象。

创建对象的时候,在构造函数中,指定父对象(此时才会挂载到对象树中)

4、通过继承自Qt内置的类,就可以达到对现有控件功能进行扩展效果。

Qt内置的QLabel,没法看到销毁的过程。为了看清楚,就创建类mylabel继承Qlabel

重写 析构函数

在析构函数中,加上日志,直观的观察到对象的释放过程了:

也可以在重写控件中的任何功能,不仅仅是析构函数~~达到功能扩张目的~~

5、乱码问题和字符集

6、如何在Qt中打印日志,作为调试信息。

使用cout固然可以,但是并不是上策(字符编码处理的不够好,也不方便统一进行关闭)

Qt中推荐使用qDebug()完成日志的打印。

相关推荐
Hhy_11071 小时前
【从零开始学习数据结构 ④】:栈 ——后进先出的艺术
c语言·数据结构·学习·visual studio
格林威1 小时前
线阵工业相机:如何计算线阵相机的行频(Line Rate)?公式+实例
开发语言·人工智能·数码相机·算法·计算机视觉·工业相机·线阵相机
Chasing Aurora1 小时前
python 安装依赖和导入模块 详解
开发语言·python·虚拟环境·import·pyenv·requirements
近津薪荼2 小时前
C++ vector容器底层深度剖析与模拟实现
开发语言·c++
木易 士心2 小时前
为什么 Promise 比 setTimeout 先执行?——JavaScript 事件循环与异步顺序完全指南
开发语言·javascript·ecmascript
念恒123062 小时前
Python(for循环)
python·学习
海清河晏1112 小时前
数据结构 | 链式队列
开发语言·数据结构·链表
晔子yy2 小时前
[JAVA探索之路]带你从零开始实现线程池
java·开发语言
Ada大侦探2 小时前
新手小白学习数据分析01----数据分析师???& 数据分析思维学习
android·学习·数据分析