🍑个人主页:Jupiter. 🚀 所属专栏:QT 欢迎大家点赞收藏评论😊


目录
-
- [` Qt Creator 新建项⽬`](#
Qt Creator 新建项⽬
) - [`认识 Qt Creator 界⾯`](#
认识 Qt Creator 界⾯
) - `项⽬⽂件解析`
- [`Qt 编程注意事项`](#
Qt 编程注意事项
) - `认识对象模型(对象树)`
- [`Qt 窗⼝坐标体系`](#
Qt 窗⼝坐标体系
)
- [` Qt Creator 新建项⽬`](#
Qt Creator 新建项⽬
- 打开 Qt Creator ,在菜单栏中选中: "⽂件" --> "新建⽂件或项⽬" ;或者使⽤快捷键:Ctrl + n;

- 选择项⽬模板
- 弹出如下对话框:

- 新建项⽬对话框⾥有五类项⽬模板:
项⽬模板 | 说明 |
---|---|
Application | Qt 应⽤程序,包括普通窗体程序和 QtQuick 程序 |
Library | 可以创建动态库、静态库以及 Qt Quick 扩展插件、QtCreator ⾃⾝插件 |
Non-Qt-Project | ⾮ Qt 项⽬。可以创建纯 C 或纯 C++ 项⽬ |
其他项⽬ | 可以创建单元测试项⽬、Qt4 设计师⾃定义控件、⼦⽬录项⽬等 |
Import Project | 导⼊项⽬。从版本控制系统管理的软件项⽬导⼊旧的项⽬ |
常⽤的只有第⼀类 Application,选择它,在右侧会看到 Qt 应⽤程序的五个⼦模板:
- Qt Widgets Application:普通窗体模板,传统基于部件的窗体界⾯程序。
- Qt Console Application:Qt 控制台应⽤程序。因为 Qt 主要⽤于图形界⾯设计,这个控制台项⽬模板基本不⽤。
- Qt for Python:在Python下⽤ LGPL 的许可来开发闭源 Qt 软件。
- Qt Quick Application: Qt 提供的⼀种⾼级⽤⼾界⾯技术,使⽤它可以⽅便快速的为移动以及嵌⼊式设备开发流畅美观的⽤⼾界⾯。Qt Quick 模块是开发 QML 应⽤的标准库,提供了使⽤ QML 创建⽤⼾界⾯所需的⼀切,包括可视化、交互、动画、模型、视图、粒⼦效果以及着⾊效果等。
💡 选择不同的项⽬模板, Qt Creator 就会在后续项⽬创建好了之后⽣成不同的基础代码
- 选择项⽬路径

- 选择构建系统
- 选择 Qt 项⽬的构建系统,使⽤默认的 "qmake" 即可。

Qt 中的构建⼯具有三种可供选择,分别是:qmake、CMake、Qbs。
- qmake: qmake 是⼀个构建⼯具(build tool),⽤于⾃动⽣成 makefile ⽂件。qmake ⽀持跨平
台构建。qmake 编辑的是⼀个后缀名为 .pro 的⽂件。 - CMake:CMake 是⼀个跨平台的构建⼯具。CMake 本⾝不是⼀个编译器,其实就是⽣成⼀个让编译器能读懂编译流程的⽂件⼯具。让 CMake ⾃动⽣成构建系统,例如 Makefile 和 Visual Studio项⽬⽂件。CMake 是⼀个第三⽅⼯具,有⾃⼰的⽂档。
- Qbs:Qbs(Qt Build Suite:Qt构建套件)同 qmake、CMake ⼀样都是构建⼯具。Qbs 号称是新⼀代的构建⼯具,⽐ qmake 编译速度更快。Qbs 没有绑定 Qt 版本,它从项⽬⽂件的⾼级项⽬描述中⽣成⼀个正确的依赖表。⽽传统的 MakeFile ⽣成⼯具如 qmake 和 CMake ,其在⽣成 MakeFile⽂件后将实际的命令交给 Make ⼯具去执⾏。
- 填写类信息设置界⾯

对于基类的选择,⽬前有三种基类:

基类 | 说明 |
---|---|
QMainWindow | 主窗⼝类,⼀般⽤于较为复杂的应⽤程序,除了中央客⼾区界⾯,还包括菜单栏、⼯具栏、状态栏以及多个可停靠的⼯具对话框等 |
QWidget | 最简单、最基本的窗体程序,⾥⾯可以放置多个控件实现程序功能 |
QDialog | 基于对话框的程序,对话框⼀般⽤于弹窗,也可以⽤于主界⾯显⽰。对话框是从QWidget继承⽽来的,并丰富了⼀些功能,如模态显⽰和返回值等 |
上述三个类之间的关系如下图:
- 选择语⾔和翻译⽂件
此处选择的语⾔是 "汉语", "英语" 这样的语⾔. ⽽不是 "编程语⾔",由于我们暂时不考虑国际化问题, 直接下⼀步即可.
- 选择 Qt 套件
- 默认只有第⼀个 "Desktop Qt 5.14.2 MinGW 64-bit",如果安装配置了多个 Qt 套件,就可以都选上。Qt 套件是指 Qt 程序从编译链接到运⾏环境的全部⼯具和 Qt 类库的集合,对于 MinGW 版本 Qt 程序⽣成和调试,⾄少需要 MinGW 中的编译器 g++(⾃动调⽤链接器)、g++ 配套的基础库、调试器 gdb 还有使⽤ MinGW 环境编译⽽成的 Qt 类库⾃⾝。默认情况下,在上⾯ Kit Selection ⾥选中全部套件。

- 选择版本控制系统
-
点击 "下⼀步" 进⼊ 项⽬管理界⾯;在项⽬管理界⾯可以设置作为⼦项⽬,以及加⼊版本控制系统管理。这两个功能暂时⽤不到,都⽤默认的 ,然后点击 "完成" 。
-
如果想把代码提交到码云或者 github, 可以在此处选择 git 作为版本控制系统.

- 最终效果
-
通过上述 8 个步骤, 完成了项⽬的创建
-
项⽬创建完成之后,Qt Creator 会直接进⼊代码编辑模式,可以看到类似下图界⾯:

认识 Qt Creator 界⾯
1. 左边栏

边栏⼦窗⼝标题栏第⼀个控件是组合框,可以选择该⼦窗⼝的功能视图类型,⽬前可以选择 8 个视图类型:
视图类型 | 说明 |
---|---|
项⽬ | 即项⽬⽂件管理视图,可以选择项⽬⾥的⽂件进⾏编辑,包括 pro ⽂件也可以⼿动编辑。 |
打开⽂档 | 当前已经打开的⽂件列表,⽂件名右边如果有 * 号,是该⽂件被修改了但尚未保存。 |
书签 | 右击代码编辑器⾏号位置,看到 "切换书签",可以给代码⾏添加书签,⽅便跳转到该位置。 |
⽂件系统 | 相当于系统⾥的⽂件资源管理器,可以查看项⽬⽂件夹在磁盘⾥的实际⽂件列表。 |
类视图 | 可以查看项⽬⾥包含的类及相应源代码⽂件⾥的成员函数、成员变量。 |
Git Branches | 查看当前分⽀ |
⼤纲 | 编辑器所显⽰的当前⽂件的⼤纲列表,如名字空间、类名、成员函数、成员变量等。 |
Tests | 测试 |
类型层次 | 当前项⽬包含的类及其基类、派⽣类列表。 |
Include Hierarchy | 包含视图,显⽰当前项⽬⾥ .h 、.cpp 以及 Qt 类库头⽂件之间的包含关系。 |
2. 代码编辑区

①和②:导航按钮 "返回" 和 "前进",这与⽹⻚浏览器的前进和后退按钮类似,可以在之前浏览的多个代码⽂件或⼀个代码⽂件⾥多个位置之间快速切换。
③:标识当前显⽰的⽂件是只读还是可写,⼀般都是可写的。
④:⽂件类型图标,当前显⽰⽂件的类型,这个控件其实是⼀个菜单按钮,点击可以弹出丰富的⽂件处理功能菜单。
⑤:打开的⽂件名,可以在多个打开的⽂件之间选择切换,与边栏的 "打开⽂档" 视图是对应的。
⑥:关闭当前显⽰的⽂档。
⑦:为当前显⽰的⽂件添加额外的C++预处理指令,⼀般⽤不着。
⑧:选择符号,可以在当前显⽰的⽂件⾥多个函数、类、成员变量等之前快速切换,与边栏"⼤纲"视图是对应的。
⑨:编辑区光标的⾏号和列号。
⑩:代码编辑区分栏,可以增加多个编辑器窗⼝,显⽰多个打开的⽂档或显⽰较⼤源码⽂件的多个位置。
- ⾏⾸区:主要⽤来显⽰代码⾏号,以及调试断点标志和代码书签标志。右击⾏⾸区可以弹出右键菜
单,菜单⾥可以切换书签、编辑书签以及设置或取消断点。 - 同⼀⾏是既可以打断点也可以设置书签的,⼆者不冲突,其实它们根本就没关系。单击⾏号前⾯的浅灰⾊空⽩区可以直接打断点,再次单击可以取消断点,另外也可以⽤快捷键 F9 设置或取消断点。
- 代码书签⼀般⽤右键菜单来设置,也可以⽤快捷键 Ctrl+M 设置或取消书签。
- 编辑区:写代码的区域。
3. UI设计界⾯
- 双击 widget.ui ⽂件,Qt Creator 会⾃动进⼊设计模式,可以对图形界⾯进⾏可视化编辑:

①:组件选择窗⼝。组件选择窗⼝分为多个组,如 Layouts、Buttons、Display Widgets 等,界⾯设计的常⻅组件都可以在组件选择窗⼝中找到。
②:UI 设计窗⼝。如果要将某个组件放置到该窗⼝上时,从组件选择窗⼝上拖放⼀个组件到窗体上即可。
③:动作编辑窗⼝。动作编辑窗⼝包括 Action Editor 以及 Signals 和 Slots 编辑器。 Action Editor 主要是⽤来新建 Action,并且通过拖拽的动作,将新建好的 Action 添加到菜单栏和⼯具栏上;Signals和 Slots 编辑器⽤于可视化地进⾏信号与槽的关联。
④:对象浏览窗⼝。⽤树状视图显⽰窗体上各组件之间的布局包含关系,视图有两列,显⽰每个组件的对象名称(ObjectName)和类名称。
⑤:属性设置窗⼝。显⽰某个选中的组件或窗体的各种属性及其取值,可以在属性设置窗⼝⾥修改这些属性的值。
4. 构建区
项⽬⽂件解析
1. pro ⽂件解析
- ⼯程新建好之后,在⼯程⽬录列表中有⼀个后缀为 ".pro" 的⽂件, ".pro" ⽂件就是⼯程⽂件 (project),它是 qmake ⾃动⽣成的⽤于⽣产 makefile 的配置⽂件。如图所⽰:

双击进⼊该⽂件,该⽂件的核⼼内容如下:
cpp
QT += core gui // Qt 包含的模块
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets //⼤于 Qt4 版本才包含 widget 模块
TARGET = QtFirst //应⽤程序名⽣成的 .exe 程序名称
TEMPLATE = app //模板类型,应⽤程序模板
SOURCES += main.cpp\ //源⽂件
widget.cpp //源⽂件
HEADERS += widget.h //头⽂件
".pro" ⽂件的写法如下:
- 注释:从 "#" 开始,到这⼀⾏结束。
- QT += core gui // Qt 包含的模块 Qt5 包含的模块如下图所⽰:

- greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 这条语句的含义是,如果
QT_MAJOR_VERSION ⼤于 4 也就是当前使⽤的 Qt5 及更⾼版本) 需要增加 widgets 模块。如果项⽬仅需⽀持 Qt5 , 也可以直接添加 "QT += widgets" ⼀句。不过为了保持代码兼容 ,最好还是按照 QtCreator ⽣成的语句编写。 - 指定⽣成的应⽤程序名:TARGET = QtDemo
- TEMPLATE = app //模板。告诉 qmake 为这个应⽤程序⽣成哪种 makefile。下⾯是可供选择的模
板:- app:建⽴⼀个应⽤程序的 makefile。这是默认值,所以如果模板没有被指定,这个将被使⽤
- lib :建⽴⼀个库的 makefile。
- vcapp:建⽴⼀个应⽤程序的 VisualStudio 项⽬⽂件。
- vclib: 建⽴⼀个库的 VisualStudio 项⽬⽂件。
- subdirs:这是⼀个特殊的模板,它可以创建⼀个能够进⼊特定⽬录的 makefile 并且为它调⽤make 的 makefile。
- ⼯程中包含的源⽂件:SOURCES += main.cpp/widget.cpp
- ⼯程中包含的头⽂件:HEADERS += widget.h
- ⼯程中包含的资源⽂件:RESOURCES += painter.qrc
- ⼯程中包含的 "ui" 设计⽂件:FORMS += widget.ui
- 配置信息:CONFIG += c++11 (使⽤ c++11 的特性) CONFIG ⽤来告诉 qmake 关于应⽤程序的置信息。
2. widget.h ⽂件解析
- 在Qt中,如果要使⽤信号与槽(signal 和 slot)的机制 就必须加⼊ Q_OBJECT 宏;
Ui::Widget *ui; 这个指针是⽤前⾯声明的 namespace Ui ⾥的 Widget 类定义的,所以指针 ui 是指向可视化设计的界⾯,后⾯要访问界⾯上的组件,都需要通过这个指针 ui 去访问。

3.main.cpp ⽂件解析
- 使⽤ Qt Creator 新建任意⼯程之后,main.cpp ⽂件中都会⾃动⽣成如下代码:

解释:
- Qt 系统提供的标准类名 声明头⽂件没有 .h 后缀;
- Qt ⼀个类对应⼀个头⽂件,类名 就是 头⽂件名;
- QApplication 为应⽤程序类;QApplication a;(a为应⽤程序对象,有且仅有⼀个)
- QApplication 管理图形⽤⼾界⾯应⽤程序的控制流和主要设置。
- QApplication 是 Qt 的整个后台管理的命脉。它包含主事件循环,在其中来⾃窗⼝系统和其它资源的所有事件处理和调度。它也处理应⽤程序的初始化和结束,并且提供对话管理。
- 对于任何⼀个使⽤ Qt 的图形⽤⼾界⾯应⽤程序,都正好存在⼀个 QApplication 对象,⽽不论这个应⽤程序在同⼀时间内是不是有 0、1、2 或更多个窗⼝。
- myWidget w; //实例化窗⼝对象
- w.show(); //调⽤show函数显⽰窗⼝
- a.exec() :程序进⼊消息循环,等待对⽤⼾输⼊进⾏响应。这⾥ main()把控制权转交给Qt,Qt 完
成事件处理⼯作,当应⽤程序退出的时候 exec() 的值就会返回。在 exec() 中,Qt 接受并处理用户和系统的事件并且把它们传递给适当的窗⼝部件。
4. widget.cpp ⽂件解析
- widget.cpp ⽂件是类 Widget 的实现代码,所有在窗体上要实现的功能添加在此⽂件中;

5. widget.ui ⽂件解析
widget.ui 是窗体界⾯定义⽂件,是⼀个 XML ⽂件,定义了窗⼝上的所有组件的属性设置、布局,及其信号与槽函数的关联等。⽤ UI 设计器可视化设计的界⾯都由 Qt ⾃动解析,并以 XML ⽂件的形式保存下来。在设计界⾯时,只需在 UI 设计器⾥进⾏可视化设计即可,⽽不⽤管 widget.ui ⽂件是怎么⽣成的。
Qt 编程注意事项
Qt 中的命名规范
-
类名:⾸字⺟⼤写,单词和单词之间⾸字⺟⼤写;
-
函数名及变量名:⾸字⺟⼩写,单词和单词之间⾸字⺟⼤写;
-
💡 Qt 偏好驼峰命名法. 这⼀点不像咱们之前课堂上偏好蛇形命名.
Qt Creator 中的快捷键
- 注释:ctrl + /
- 运⾏:ctrl + R
- 编译:ctrl + B
- 字体缩放:ctrl + ⿏标滑轮
- 查找:ctrl + F
- 整⾏移动:ctrl + shift + ⬆/⬇
- 帮助⽂档:F1
- ⾃动对⻬:ctrl + i;
- 同名之间的 .h 和 .cpp 的切换:F4
- ⽣成函数声明的对应定义: alt + enter
使⽤帮助⽂档
打开帮助⽂档有三种⽅式. 实际编程中使⽤哪种都可以.
- 光标放到要查询的类名/⽅法名上, 直接按 F1
- Qt Creator 左侧边栏中直接⽤⿏标单击 "帮助" 按钮:

- 找到 Qt Creator 的安装路径,在 "bin" ⽂件夹下找到 assistant.exe,双击打开;

双击打开后的界面
认识对象模型(对象树)
在 Qt 中创建很多对象的时候会提供⼀个 Parent 对象指针,下⾯来解释这个 parent 到底是⼲什么的?
-
QObject 是以对象树的形式组织起来的。
- 当创建⼀个 QObject 对象时,会看到 QObject 的构造函数接收⼀个 QObject 指针作为参数,这个参数就是 parent,也就是⽗对象指针。
- 这相当于,在创建 QObject 对象时,可以提供⼀个其⽗对象,我们创建的这个 QObject 对象会⾃动添加到其⽗对象的 children( ) 列表。
- 当⽗对象析构的时候,这个列表中的所有对象也会被析构。(
注意
: 这⾥的⽗对象并不是继承意义上的⽗类!)这种机制在 GUI 程序设计中相当有⽤。例如,⼀个按钮有⼀个 QShortcut(快捷键)对象作为其⼦对象。当删除按钮的时候,这个快捷键理应被删除。这是合理的。
-
QWidget 是能够在屏幕上显⽰的⼀切组件的⽗类。
- QWidget 继承⾃ QObject ,因此也继承了这种对象树关系。⼀个孩⼦⾃动地成为⽗组件的⼀个⼦组件。因此,它会显⽰在⽗组件的坐标系统中,被⽗组件的边界剪裁。例如,当⽤⼾关闭⼀个对话框的时候,应⽤程序将其删除,那么,我们希望属于这个对话框的按钮、图标等应该⼀起被删除。事实就是如此,因为这些都是对话框的⼦组件。
- 当然,我们也可以⾃⼰删除⼦对象,它们会⾃动从其⽗对象列表中删除。⽐如,当我们删除了⼀个⼯具栏时,其所在的主窗⼝会⾃动将该⼯具栏从其⼦对象列表中删除,并且⾃动调整屏幕显⽰。
-
Qt 引⼊对象树的概念,在⼀定程度上解决了内存问题
。- 当⼀个 QObject 对象在堆上创建的时候,Qt 会同时为其创建⼀个对象树。不过,
对象树中对象的 顺序是没有定义的
。这意味着,销毁这些对象的顺序也是未定义的。 - 任何对象树中的 QObject 对象 delete 的时候,如果这个对象有 parent,则⾃动将其从 parent 的children() 列表中删除;如果有孩⼦,则⾃动 delete 每⼀个孩⼦。Qt 保证没有 QObject 会被delete 两次,这是由析构顺序决定的。
- 当⼀个 QObject 对象在堆上创建的时候,Qt 会同时为其创建⼀个对象树。不过,
如果 QObject 在栈上创建,Qt 保持同样的⾏为。正常情况下,这也不会发⽣什么问题。来看下⾯的代码⽚段:
作为⽗组件的 window 和作为⼦组件的 quit 都是 QObject 的⼦类(事实上,它们都是QWidget的⼦类,⽽QWidget 是 QObject 的⼦类)。这段代码是正确的,quit 的析构函数不会被调⽤两次,因为标准 C++ 要求,局部对象的析构顺序应该按照其创建顺序的相反过程
。因此,这段代码在超出作⽤域时,会先调⽤ quit 的析构函数,将其从⽗对象 window 的⼦对象列表中删除,然后才会再调⽤window 的析构函数。
但是,如果我们使⽤下⾯的代码:
情况⼜有所不同,析构顺序就有了问题。我们看到,在上⾯的代码中,作为⽗对象的 window 会⾸先被析构,因为它是最后⼀个创建的对象。在析构过程中,它会调⽤⼦对象列表中每⼀个对象的析构函数,也就是说, quit 此时就被析构了。然后,代码继续执⾏,在 window 析构之后,quit 也会被析构,因为 quit 也是⼀个局部变量,在超出作⽤域的时候当然也需要析构。但是,这时候已经是第⼆次调⽤ quit 的析构函数了,C++ 不允许调⽤两次析构函数,因此,程序崩溃了。
由此我们看到,Qt 的对象树机制虽然在⼀定程度上解决了内存问题,但是也引⼊了⼀些值得注意的事情。
- 💡 在 Qt 中,尽量在构造的时候就指定 parent 对象,并且⼤胆在堆上创建。
Qt对象树如图:

- 对象树确保的是先释放⼦节点的内存, 后释放⽗节点的内存.
- ⽽析构函数的调⽤顺序则不⼀定遵守上述要求. 因为上面看到⼦节点的析构执⾏顺序反⽽在⽗节点析构顺序之后.
注意:
调⽤析构函数和释放内存并⾮是同⼀件事情
Qt 窗⼝坐标体系
- Qt坐标系使用的是左手坐标系。
- 坐标体系:以左上⻆为原点(0,0),X向右增加,Y向下增加。

- 对于嵌套窗⼝,其坐标是相对于⽗窗⼝来说的。
⽰例:使⽤Qt中的坐标系设置控件的位置;

- 运⾏结果如下图⽰:
