宁夏回族自治区网站建设_网站建设公司_腾讯云_seo优化
2025/12/18 18:19:57 网站建设 项目流程

1.QT概述

什么是QT,QT是一个跨平台的C++图形用户界面应用程序框架。它可以为程序开发者提高建立图形化界面的所有功能。它是完全面向对象的,很容易进行扩展。QT为开发者提供了一种基于基础组件的开发模式,开发者可以通过简单的拖拽和组合来实现复杂的应用程序,同时也可以使用C++来进行更高级的开发。

图形化界面:指采用图像的方式显示计算机的用户操作界面,是计算机与使用者之间的对话接口。

2.设计一个QT程序

2.1使用图形化的方式实现一个按钮

这里在创建QT项目的时候要选择QWidegt,表示创建一个类来继承哪个类,这个创建出来的类就包含了基类的大部分功能。

创建项目以后进入到主界面是这样的

进入到图形设计界面,拖拽PushButton创建一个按键

回到主界面,编译代码并运行

2.2使用代码创建一个按钮

这里我们来到Widget.cpp的界面,为创建按钮写一部分代码

运行以后看到确实也出现了一个按钮。

虽然看起来两种方式不太一样,但本质上是一样的,我我们可以在项目文件夹种找到一个带有build开头加项目名称的文件,然后里面有一个ui_widget.h的文件

打开这个ui_widget.h的文件,可以看到系统已经为我们在ui_widget类中自动创建了一个PushButton的对象。这是QT的编译器使用qmake的方式根据xml来进行的一种元编程的方式,即通过一些代码帮我们自动生成C++代码的技术。

3.文件解析

在我们创建项目以后,QT自动为我们生成了许多文件,这里我们对其中的一些进行解析。

3.1widget.h文件解析

Q_OBJECT:这是一个QT的宏,这个宏允许使用信号和槽机制,后续我们会讲到。

QWidget:QWidget窗口类的头文件

UI::Widget *ui:通过这个指针可以访问UI设计界面中的任意控件。

在ui_widget.h文件中,UI::Widget是继承于UI_Widget这个UI设计界面类的,也就是代表UI::Widget能访问设计界面中公有的所有成员函数与成员变量。通过一个指针ui就能访问到UI设计界面的任意控件。

3.2widget.cpp解析

widget.cpp ⽂件是类 Widget 的实现代码,所有在窗体上要实现的功能添加在此⽂件中。

3.3widget.ui文件解析

widget.ui 是窗体界⾯定义⽂件,是⼀个 XML ⽂件,定义了窗⼝上的所有组件的属性设置、布局,及其信号与槽函数的关联等。⽤ UI 设计器可视化设计的界⾯都由 Qt ⾃动解析,并以 XML ⽂件的形式保存下来。在设计界⾯时,只需在 UI 设计器⾥进⾏可视化设计即可,⽽不⽤管 widget.ui ⽂件是怎么⽣成的。

4.认识对象模型(对象树)

4.1QObject 是以对象树的形式组织起来的。

在QT中创建很多对象的时候都要提供一个Parent对象指针,就例如:

这里传的this指针代表这两个对象将当前widget类作为他们的父对象了。为什么要创建一个父对象?

首先在我们创建PushButton这个按钮的时候我们并没有对它进行析构释放,这是否会造成内存泄漏?并不会,这就归咎于对象树的作用了。

当创建一个QObject对象的时候,QObject的构造函数会解释一个QObject指针作为参数初始化它的父对象指针。

也就是说在创建一个QObject对象的时候,显示的传递一个QObject指针,创建的这个对象就会自动被加入到父对象大的children()列表。

当整个程序执行完以后,窗口Widget会去释放自身,发现它还有子对象,就会先去调用子对象的析构函数。当所有子对象释放了,该父对象才会释放,也就保证了它的每一个子对象不需要显示的析构和释放。

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

QPushButton源码中的构造:

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

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

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

QWigdet的声明:

4.3QT引入对象树的概念,在一定程度上解决了内存泄漏的问题

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

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

如果在像在这样栈上创建两个对象,正常情况下不会发生什么问题

在C++中局部对象的析构顺序是按照创建顺序的相反顺序来的,此处quit先析构,将自己从qwindow的子对象列表删除,然后qwindow再析构,这是没有问题的。

但是如果是一下这种情况,就会出现析构两次quit的问题:

qwindow先定义首先会析构,然后去调用自己子对象中quit的析构,等quit析构完以后,此时quit还会进行一次它自己原本应该进行的析构,结果就会程序就崩溃了,quit析构了两次。

所以在QT中创建对象尽量在构造的时候就指定父对象,然后在堆上创建。

QT对象图

4.4代码演示-父对象自动析构子对象

创建一个新的类

指定继承的类

修改继承类和增加一个析构函数

定义析构函数和显示调试信息

在widget.h中创建一个按键并显示

编译与运行代码

这里MyPushButto继承QPushButton,使用了其父类的成员函数创建了一个按钮

关闭窗口的时候wiget先被析构,button被自动释放了。对象树确保的是先释放⼦节点的内存, 后释放⽗节点的内存。⽽析构函数的调⽤顺序则不⼀定遵守上述要求.。因此看到⼦节点的析构执⾏顺序反⽽在⽗节点析构顺序之后。

5.总结

通过本文的学习,我们正式推开了 Qt 开发的大门。我们不仅认识了 Qt 这个强大的跨平台 C++ 图形用户界面框架,还通过实战掌握了构建 Qt 程序的两个核心维度:

  1. 开发模式:无论是直观的 UI 设计器拖拽,还是灵活的纯代码编写,我们通过解析ui_widget.h等底层文件,明白了它们本质上殊途同归,最终都由 Qt 的元编程机制转化为标准的 C++ 代码。

  2. 核心机制:文章重点剖析了 Qt 的对象树(Object Tree)模型。这是 Qt 区别于普通 C++ 开发的重要特性,通过QObject的父子关系链,Qt 巧妙地实现了内存的自动回收,极大地降低了内存泄漏的风险。

理解对象树与文件结构,是成为一名合格 Qt 开发者的基石。掌握了这些基础,我们便有了构建更复杂、更健壮的 GUI 应用程序的能力。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询