【QT】Qt初识(Qt背景、Qt Creator创建项目操作、项目代码解释等)
Qt 是一个跨平台的 C++ 图形界面应用程序框架 。它为应用程序开发者提供了建立艺术级图形界面所需的所有功能。
Q t Qt Qt 是一个跨平台的 C C C++ 图形用户界面( G U I GUI GUI)应用程序框架 。它为应用程序开发者提供了建立艺术级图形界面所需的所有功能。
前言 —— Qt 背景
什么是 Qt ?
Q t Qt Qt 是一个跨平台的 C C C++ 图形用户界面( G U I GUI GUI)应用程序框架 。它为应用程序开发者提供了建立艺术级图形界面所需的所有功能。它是完全面向对象的,很容易扩展。 Q t Qt Qt 为开发者提供了一种基于组件的开发模式,开发者可以通过简单的拖拽和组合来实现复杂的应用程序( Q T − D e s i g n e r QT-Designer QT−Designer),同时也可以使用 C C C++ 语言进行高级开发。

图形用户界面 :指采用图形方式显示的计算机操作用户界面,是计算机与其使用者之间的对话接口,是计算机系统的重要组成部分。
1. 客户端开发
客户端( C l i e n t Client Client)或称为用户端,是指与服务器相对应,为客户提供本地服务的程序。除了一些只在本地运行的应用程序之外,一般安装在普通的客户机上,需要与服务端互相配合运行。
服务端:一般采用 L i n u x Linux Linux 操作系统的服务器,在客户端背后,负责处理来自客户端的请求。
客户端:直接和用户打交道的这一端程序。如: c h r o m e chrome chrome、 c c t a l k cctalk cctalk、 q q qq qq 音乐、 s t e a m steam steam ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ······ ⋅⋅⋅⋅⋅⋅ 等。
虽然大部分客户端程序,是需要有背后的服务器做支撑的,但是确实也有些程序,是不需要服务器的(离线应用、单机游戏)。这样的程序(比如画图板、计算器 ⋅ ⋅ ⋅ ··· ⋅⋅⋅)同样也是直接和客户打交道,因此也可以称为客户端程序。
客户端开发的主要任务:编写和用户交互的界面。
和用户交互的界面,主要有两种典型的风格:
-
命令行界面 / / / 终端界面(黑框框): T U I TUI TUI( g c c gcc gcc、 g d b gdb gdb ⋅ ⋅ ⋅ ··· ⋅⋅⋅)(专业软件 − - −给程序员用的)
-
图形化界面: G U I GUI GUI( W i n d o w s Windows Windows 操作系统 ⋅ ⋅ ⋅ ··· ⋅⋅⋅)(给普通用户用的)

准确的说, Q t Qt Qt 特指用来进行桌面应用开发(电脑上写的程序)涉及到的一套技术。 Q t Qt Qt 无法开发网页前端,也不能开发移动应用(目前 Q t Qt Qt 官方也支持移动应用开发了,但是还是不常用)。
2. 开发 GUI 工具
在 W i n d o w s Windows Windows 编写 G U I GUI GUI 程序时,也是有很多解决方案的, Q t Qt Qt 只是其中一种。
一些常见的 G U I GUI GUI 工具:
-
W i n d o w s A P I Windows\ API Windows API: W i n d o w s Windows Windows 系统提供原生的 A P I API API,开发起来非常原始,也非常繁琐。
-
M F C MFC MFC、 V C 6.0 VC\ 6.0 VC 6.0:当年(上世纪 90 90 90 年代)影响力非常深远,但现在早已不更新了。
1991 1991 1991 年,计算机诞生了许多神奇的东西,也称作计算机的奇迹年:
如: Q t Qt Qt、 p y t h o n python python、 v i m vim vim、 O p e n G L OpenGL OpenGL、 L i n u x Linux Linux ……
- Q t Qt Qt( 1991 1991 1991 年左右)诞生了, Q t Qt Qt 仍然在不停地推陈出新,更新新的版本,至今还非常有生命力。
后来微软,自己搞了一个编程语言叫 C C C#( C C C s h a r p sharp sharp)
-
W i n d o w s F o r m s Windows\ Forms Windows Forms:给 C C C#( . n e t .net .net)量身定做的一套开发 G U I GUI GUI 技术体系。
-
E l e c t r o n Electron Electron:本质上是把基于 h t m l html html 这样的网页,打包成一个 w i n d o w s windows windows 上运行的客户端程序。
E l e c t r o n Electron Electron 这个技术体系,最初是用来开发 a t o m atom atom 文本编辑器的( g i t h u b github github 开发的),后来 a t o m atom atom 被微软搞的 v s c o d e vscode vscode 给干趴了。
比较大的缺点:开发出来的程序,运行效率低于上面介绍的一些原生开发的技术体系。
因此,虽然 Q t Qt Qt 只是上述解决方案中的一种,但仍然属于是其中最能打的那一个(商业公司的产品,使用 Q t Qt Qt 非常多,对应的就业岗位就相比于其他的技术方案也是更多的):
Q t Qt Qt 的优势:能够跨平台。不仅仅支持 W i n d o w s Windows Windows,也支持 L i n u x Linux Linux,还支持 M a c Mac Mac,而且运行效率还不低,妥妥属于六边形战士了。
3. 框架
框架,本质上是一群大佬发明出来的,方便让我们这种刚入门的程序员,写出来的代码比较靠谱。自由,灵活,就代表着越容易出错;框架,就是在限制程序员的自由。
可以理解为,我们学会 C C C++ 的语法,就相当于刚学会下象棋的规则,如果没有一个棋谱(框架)辅助你下棋(写代码),很容易走出第一步走王这种离谱操作。
库和框架都是属于,大佬把一些代码写好了,让你去使用:
-
库:被程序员调用的。(程序员是主体)
-
框架:程序员配合框架,(框架是主体)完善填充框架中留出的一些细节。
比如 J a v a Java Java,对于框架就更加依赖,因为其有比较统一的社区和框架 —— S p r i n g Spring Spring。
编写 C C C++ 代码,框架也是很重要的,但是 C C C++ 的生态是割裂的,离散的,不同开源社区 / / / 大厂,各自都有各自的框架(没有一个统一的标准)。
相比之下,像 Q t Qt Qt 这种,能被大家共同认可的框架,在整个 C C C++ 生态中是不多见的。
4. Qt 支持的系统
Q t Qt Qt 的主要优势之一就是能够跨平台,因此其不仅仅支持 W i n d o w s Windows Windows,也支持 L i n u x Linux Linux,还支持 M a c Mac Mac,甚至还有嵌入式系统也能用到 Q t Qt Qt 开发。
- W i n d o w s Windows Windows(各个版本)
主要应用领域。
- L i n u x Linux Linux(各种发行版),尤其是 L i n u x Linux Linux 中的 K D E KDE KDE 桌面就是基于 Q t Qt Qt 构建的
L i n u x Linux Linux 主要是给服务器使用,服务器不需要图形化界面。大部分都是程序员在用,使用 T U I TUI TUI,基于命令行操作,效率会更高。但是也有少量用户,使用 L i n u x Linux Linux 作为电脑桌面: G N O M E GNOME GNOME(基于 G T K GTK GTK 构建的)、 K D E KDE KDE(基于 Q t Qt Qt 构建的)。
- M a c Mac Mac 系统
苹果公司自己的操作系统,但是价格实在昂贵,性价比远远不如 w i n d o w s windows windows 电脑,而且性能基本也比不过,没有听说哪个人推荐用 M a c Mac Mac 打游戏的哈哈。
- 嵌入式系统
嵌入式系统也是 Q t Qt Qt 实际开发中的一个主战场。日常使用的冰箱、洗衣机、路由器、投影仪 …… 这些设备内部也有计算机。但是这种设备的计算机硬件配置就不需要很高了。(低配置,低成本)
因此,有些嵌入式系统,也是需要运行图形化界面程序的,这个时候, Q t Qt Qt 就可以起到作用了,尤其是在一些工业设备上。(但现在也受到了安卓的挑战)
5. Qt 的优点
通过上面的介绍,想必已经对 Q t Qt Qt 有了大概的认识,下面总结了一下 Q t Qt Qt 的主要优点。
-
跨平台,几乎支持所有的平台。
-
接口简单,容易上手,学习 Q t Qt Qt 框架对学习其他框架有参考意义。
-
一定程度上简化了内存回收机制。(半自动的垃圾回收,能够简化内存释放,也能够小的影响程序的运行效率)
-
开发效率高,能够快速的构建应用程序。
-
有很好的社区氛围,市场份额在缓慢上升。
-
可以进行嵌入式开发。
6. Qt 开发环境
在软件开发中,并非是越新越好。在进行商业开发的时候,相比之下,引入新的特性,不如优先确保不引入严重的问题。
Q t Qt Qt 开发环境,需要安装 3 3 3 个部分:
- C C C++ 编译器( g c c gcc gcc, c l . e x e cl.exe cl.exe …)
注意:编译器 ! = != != I D E IDE IDE,编译器只是 I D E IDE IDE 调用的一个程序。
- Q t Qt Qt S D K SDK SDK(软件开发工具包)
比如, w i n d o w s windows windows 版本 Q t Qt Qt S D K SDK SDK 里已经内置了 C C C++ 的编译器(内置的编译器是 m i n g w mingw mingw)
-
Q t Qt Qt 的集成开发环境( I D E IDE IDE)
(1) Q t Qt Qt 官方提供的 Q t C r e a t o r Qt\ Creator Qt Creator
最容易入门,最容易上手的方式,开箱即用,不需要任何额外的配置,比较适合新手。
(2) V i s u a l S t u d i o Visual\ Studio Visual Studio
功能更强,但是需要额外的配置更多,有些公司开发商业 Q t Qt Qt 程序的时候,可能会使用 V S VS VS,需 要给 V S VS VS 安装 Q t Qt Qt 插件,并且需要把 Q t Qt Qt S D K SDK SDK 使用 V S VS VS 编译器重新编译(现在也方便一些,有预编译好的版本)。
(3) E c l i p s e Eclipse Eclipse
E c l i p s e Eclipse Eclipse 并非只是 J a v a Java Java 的 I D E IDE IDE,其本身是一个 I D E IDE IDE 平台,可以搭配不同的插件构成不同的 I D E IDE IDE。目前 E c l i p s e Eclipse Eclipse 市场份额受到的冲击很大:重量级工具,有 J e t B r a i n s JetBrains JetBrains;轻量级工具,有 V S C o d e VSCode VSCode。
其实说是安装 3 3 3 个东西,其实只要安装一个 Q t Qt Qt S D K SDK SDK,另外两个也就都有了。
一、 Qt Creator 的基础使用
1. Qt SDK 的下载安装
注意:安装软件的时候,所在的目录,不要带中文,也不要带特殊符号,也不要带空格。
Q t Qt Qt 下载官网:http://download.qt.io/archive/qt/。
打开官网,进行下载即可(我这里下载的版本是 5.14.2 5.14.2 5.14.2):

2. Qt 环境变量的配置
- 找到 Q t Qt Qt 的安装路径,复制 b i n bin bin 路径:

- 此电脑 ------> 鼠标右键, 属性 ------> 高级系统设置 ------> 环境变量 ------> P a t h Path Path:

再连续点三个确定保存即可。
为什么要设置环境变量?
环境变量是在操作系统中一个具有特定名字的对象,它包含了一个或者多个应用程序将要使用到的信息。
例如, W i n d o w s Windows Windows 和 D O S DOS DOS 操作系统中的 p a t h path path 环境变量,当要求系统运行一个程序而没有告诉它程序所在的完整路径时,系统除了在当前目录下面寻找此程序外,还会到 p a t h path path 中指定的路径去找。
在 W i n d o w s Windows Windows 上设置 Q t Qt Qt 的环境变量是为了能够在命令行或其他应用程序中直接访问 Q t Qt Qt 相关的命令和工具( . e x e .exe .exe 和 . d l l .dll .dll 动态库)。
3. Qt SDK 中自带的工具程序
3.1 Assistant 5.14.2
Q t Qt Qt 自带离线版本的官方文档。

虽然 Q t Qt Qt 也有中文文档(非官方的),但还是建议去看官网的英文文档(阅读英文文档是程序员的必备技能,要耐心去看)。
3.2 Designer 5.14.2
Q t Qt Qt 设计师:图形化的设计界面的工具。

通过拖拽空间的方式来快速生成界面,后面会经常使用,但是是搭配 Q t C r e a t o r Qt\ Creator Qt Creator 来使用。
3.3 Linguist 5.14.2
Q t Qt Qt 语言家:作用是对国际化进行支持。

允许你单独创建一个语言配置文件,把界面上需要用到的各种文字都配置到文件中,并且在文件中提前的把各种语言的翻译都配置进去,就可以起到一键切换语言的效果。
3.4 Qt Creator 4.11.1
Q t Qt Qt 的集成开发环境:学习 Q t Qt Qt 过程中主要使用的工具。

4. Qt Creator 创建项目操作
4.1 新建项目
打开 Q t C r e a t o r Qt\ Creator Qt Creator,在菜单栏中选中:文件 --------> 新建文件或项目(或者使用快捷键: C t r l + n Ctrl + n Ctrl+n):

4.2 选择项目模板
弹出如下对话框,选择不同的项目模板, Q t C r e a t o r Qt\ Creator Qt Creator 就会在后续项目创建好了之后生成不同的基础代码。
Q t Qt Qt 不仅仅支持 C C C++,也支持 P y t h o n Python Python 和 J a v a Java Java。
Q t Q u i c k Qt\ Quick Qt Quick 是 Q t Qt Qt 搞出来的一套新的用来开发 G U I GUI GUI 的方式。

新建项目对话框里有五类项目模板:
| 项目模板 | 说明 |
|---|---|
| A p p l i c a t i o n Q t Application\ Qt Application Qt | 应用程序,包括普通窗体程序和 Q t Q u i c k QtQuick QtQuick 程序 |
| L i b r a r y Library Library | 可以创建动态库、静态库以及 Q t Q u i c k Qt\ Quick Qt Quick 扩展插件、 Q t C r e a t o r QtCreator QtCreator 自身插件 |
| 其他项目 | 可以创建单元测试项目、 Q t 4 Qt4 Qt4 设计师自定义控件、子目录项目等 |
| N o n − Q t Non-Qt Non−Qt P r o j e c t Project Project | 非 Q t Qt Qt 项目。可以创建纯 C C C 或纯 C C C++ 项目 |
| I m p o r t P r o j e c t Import\ Project Import Project | 导入项目。从版本控制系统管理的软件项目导入旧的项目 |
常用的只有第一类 A p p l i c a t i o n Application Application,选择它,在右侧会看到 Q t Qt Qt 应用程序的五个子模板:
| 子模板 | 说明 |
|---|---|
| Q t W i d g e t s A p p l i c a t i o n Qt\ Widgets\ Application Qt Widgets Application | 普通窗体模板,传统基于部件的窗体界面程序 |
| Q t C o n s o l e A p p l i c a t i o n Qt\ Console\ Application Qt Console Application | Q t Qt Qt 控制台应用程序。因为 Q t Qt Qt 主要用于图形界面设计,这个控制台项目模板基本不用 |
| Q t f o r P y t h o n Qt\ for\ Python Qt for Python | 在 P y t h o n Python Python 下用 L G P L LGPL LGPL 的许可来开发闭源 Q t Qt Qt 软件 |
| Q t Q u i c k A p p l i c a t i o n Qt\ Quick\ Application Qt Quick Application | Q t Qt Qt 提供的一种高级用户界面技术,使用它可以方便快速的为移动以及嵌入式设备开发流畅美观的用户界面。 Q t Q u i c k Qt\ Quick Qt Quick 模块是开发 Q M L QML QML 应用的标准库,提供了使用 Q M L QML QML 创建用户界面所需的一切,包括可视化、交互、动画、模型、视图、粒子效果以及着色效果等 |
4.3 选择项目路径
给 Q t Qt Qt 项目命名及选择保存项目的路径。

4.4 选择构建系统
Q t Qt Qt 中的构建工具有三种可供选择,使用默认的 q m a k e qmake qmake 即可。
q m a k e qmake qmake 是 Q t Qt Qt 的老牌构建工具了; C M a k e CMake CMake 并非是 Q t Qt Qt 专属,很多开源项目都会使用 C M a k e CMake CMake; Q b s Qbs Qbs 是新一代 Q t Qt Qt 的构建工具(实际上使用的人非常少)。
构建系统,通过 Q t Qt Qt 写的程序,涉及到一系列的元编程技术 —— 通过代码来实现代码:
Q t Qt Qt 框架会在编译的时候,自动先调用一系列的生成工具,基于你自己写的代码,生成一系列其他的 C C C++ 代码,最终编译的代码,也是最终生成的这些代码。
| 构建工具 | 说明 |
|---|---|
| q m a k e qmake qmake 是一个构建工具,用于自动生成 m a k e f i l e makefile makefile 文件 | q m a k e qmake qmake 支持跨平台构建。 q m a k e qmake qmake 编辑的是一个后缀名为 . p r o .pro .pro 的文件 |
| C M a k e CMake CMake 是一个跨平台的构建工具 | C M a k e CMake CMake 本身不是一个编译器,其实就是生成一个让编译器能读懂编译流程的文件工具。让 C M a k e CMake CMake 自动生成构建系统,例如 M a k e f i l e Makefile Makefile 和 V i s u a l S t u d i o Visual\ Studio Visual Studio 项目文件。 C M a k e CMake CMake 是一个第三方工具,有自己的文档 |
| Q b s Qbs Qbs( Q t B u i l d S u i t e Qt\ Build\ Suite Qt Build Suite: Q t Qt Qt 构建套件)同 q m a k e qmake qmake、 C M a k e CMake CMake 一样都是构建工具 | Q b s Qbs Qbs 号称是新一代的构建工具,比 q m a k e qmake qmake 编译速度更快。 Q b s Qbs Qbs 没有绑定 Q t Qt Qt 版本,它从项目文件的高级项目描述中生成一个正确的依赖表。而传统的 M a k e F i l e MakeFile MakeFile 生成工具如 q m a k e qmake qmake 和 C M a k e CMake CMake,其在生成 M a k e F i l e MakeFile MakeFile 文件后将实际的命令交给 M a k e Make Make 工具去执行。 Q t Qt Qt 官方声明,因市场原因,弃用 Q b s Qbs Qbs |
对于 Q t Qt Qt 用户来说, q m a k e qmake qmake 是当前使⽤最广泛的构建工具, C M a k e CMake CMake 其次。
4.5 填写类信息设置界面
选择基类和 u i ui ui 界面文件。
使用 Q t C r e a t o r Qt\ Creator Qt Creator 创建项目,会自动生成一部分代码出来,生成的代码就包含了一个类。
此处就是要选择这个自动生成的类的基类是谁:
-
Q M a i n W i n d o w QMainWindow QMainWindow:完整的应用程序窗口(可以包含菜单栏,工具栏,任务栏 …)
-
Q W i d g e t QWidget QWidget:表示一个控件(窗口上的一个具体的元素:输入框,下拉框,按钮 …)
-
Q D i a l o g QDialog QDialog:表示一个对话框
Q t Qt Qt 中内置的类都是以 Q Q Q 前缀开头的!
Q t Qt Qt 中创建图形化界面程序,有两种方式:
-
直接通过 C C C++ 代码的方式搭建界面
-
通过 f r o m f i l e from\ file from file,以图形化的方式来生成界面
此时,就可以用 Q t D e s i g n e r Qt\ Designer Qt Designer 或者使用 Q t C r e a t o r Qt\ Creator Qt Creator 来编辑这个 u i ui ui 文件,从而以图形化的方式快速方便的生成图形界面。

注意:此处生成的文件名与类名是高度相关的。( C C C++ 对这样的关联并非是强制的,但是推荐这样做; J a v a Java Java 要求类名和文件名必须保持一致)
对于基类的选择,目前有三种基类:
| 基类 | 说明 |
|---|---|
| Q M a i n W i n d o w QMainWindow QMainWindow | 主窗口类,一般用于较为复杂的应用程序,除了中央客户区界面,还包括菜单栏、工具栏、状态栏以及多个可停靠的工具对话框等 |
| Q W i d g e t QWidget QWidget | 最简单、最基本的窗体程序,里面可以放置多个控件实现程序功能 |
| Q D i a l o g QDialog QDialog | 基于对话框的程序,对话框一般用于弹窗,也可以用于主界面显示。对话框是从 Q W i d g e t QWidget QWidget 继承而来的,并丰富了一些功能,如模态显示和返回值等 |
上述三个类之间的关系如下图所示:

4.6 选择语言和翻译文件
直接点击下一步进入下一个界面即可。(此处选择的语言是汉语,英语这样的语言,而不是编程语言)
选择翻译文件(对应的语言),和国际化相关,一般不关心。

4.7 选择 Qt 套件
默认只有第一个
Desktop Qt 5.14.2 MinGW 64-bit,如果安装配置了多个 Q t Qt Qt 套件,就可以都选上。
选择一下基于哪个编译器的 Q t S D K Qt\ SDK Qt SDK 来构建后续代码。

Q t Qt Qt 套件是指 Q t Qt Qt 程序从编译链接到运行环境的全部工具和 Q t Qt Qt 类库的集合,对于 M i n G W MinGW MinGW 版本 Q t Qt Qt 程序生成和调试,至少需要 M i n G W MinGW MinGW 中的编译器 g g g++(自动调用链接器)、 g g g++ 配套的基础库、调试器 g d b gdb gdb 还有使用 M i n G W MinGW MinGW 环境编译而成的 Q t Qt Qt 类库自身。
默认情况下,在上面 K i t S e l e c t i o n Kit\ Selection Kit Selection 里选中全部套件。
4.8 选择版本控制系统
在项目管理界面可以设置作为子项目,以及加入版本控制系统管理,这里我添加了 g i t git git。

4.9 最终效果
项目创建完成之后, Q t C r e a t o r Qt\ Creator Qt Creator 会直接进入代码编辑模式,可以看到类似下图界面。

二、项目代码解释
1. main.cpp
Q t C r e a t o r Qt\ Creator Qt Creator 帮我们自动生成好了 m a i n main main 函数,即项目程序的执行入口。
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
-
main函数的形参:(1)
int argc:命令行个数(2)
char* argv[]:命令行参数 -
QApplication:编写一个Qt的图形化界面程序,一定需要有QApplication对象! -
Widget:刚刚创建项目的时候,填写的生成的类名。(Widget继承父类QWidget)QWidget提供了 2 2 2 个接口:(1)
.show():让控件显示出来(2)
.hide():让控件隐藏起来 -
exec():表示让程序执行起来(跑起来)
2. widget.h
存放的是我们刚刚创建项目时,填写的生成的 W i d g e t Widget Widget 类的声明。
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
- 确保头文件只被包一次( h e a d e r g u a r d header\ guard header guard):
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
// ...
#endif // WIDGET_H
其实不推荐这么写,现在一般直接用 pragma once:
#pragam once
#include <QWidget>
class Widget : public QWidget:继承创建项目时所选的父类QWidget。
这个类是 Qt SDK 内置的,要想使用这个类,就必须包含对应的头文件 #include <QWidget>。
Qt的设定:使用Qt内置的类,包含的头文件的名字与类名是保持一致的。
Q_OBJECT:是一个 Q t Qt Qt 内置的宏。
宏的本质是文本替换,Q_OBJECT 展开之后就是一大堆代码。 Q t Qt Qt 有一个非常核心的机制:信号和槽,如果某个类想要使用信号和槽,就需要引入 Q_OBJECT 这个宏。
- 构造函数的声明
Widget(QWidget *parent = nullptr);:把新创建的对象Widget挂到对象树上。
Qt 引入了对象树机制。创建的 Qt 的对象,就可以把这个对象给挂到对象树上,往树上挂的时候就需要指定父节点(对象树是一个 N N N 叉树)。
3. widget.cpp
存放的是我们刚刚创建项目时,填写的生成的 W i d g e t Widget Widget 类的定义。
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget(
{
delete ui;
}
-
#include "widget.h":创建项目时生成的头文件 -
#include "ui_widget.h":form file被qmake生成的头文件 -
构造函数
widget的实现:
4. widget.ui(form file)
直接双击 u i ui ui 文件,此时 Q t C r e a t o r Qt\ Creator Qt Creator 就会调用 D e s i g n e r Designer Designer,打开 u i ui ui 文件。(图形化的界面编辑器)

这个时候再点回编辑界面,就可以看到 w i d g e t . u i widget.ui widget.ui 的代码:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Widget</class>
<widget class="QWidget" name="Widget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Widget</string>
</property>
</widget>
<resources/>
<connections/>
</ui>
这个格式称为 x m l xml xml 格式。 x m l xml xml 和 h t m l html html 非常类似,都是使用成对的标签来表示数据。
这里 x m l xml xml 的标签有哪些,表示什么含义,都是开发 Q t Qt Qt 的大佬们自定义的,没有统一的标准。(也就是说,这里标签的具体含义我们不需要去关注,只要知道 u i ui ui 文件本质上是一个 x m l xml xml 即可)
h t m l html html 虽然也是通过标签来表示,但是 h t m l html html 的标签都是固定的,每个标签是啥含义,都是由一个专门的标准委员会制定的,所有的浏览器也是按照同样的规则来解释的。
Q t Qt Qt 中使用的 x m l xml xml 文件就是去描述这个界面是啥样的,进一步 q m a k e qmake qmake 会调用相关的工具,依据这个 x m l xml xml 文件生成一些 C C C++ 代码,从而把完整的界面构造出来。
5. Empty.pro
. p r o .pro .pro 文件是 Q t Qt Qt 项目的工程文件,也是 q m a k e qmake qmake 工具构建时候的重要依据。
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
widget.cpp
HEADERS += \
widget.h
FORMS += \
widget.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
-
QT += core gui:要引入的Qt模块,后面引入其他的模块时可能会修改这里 -
CONFIG += c++11:编译选项,这里是按照C++11来编译

Q t C r e a t o r Qt\ Creator Qt Creator 把整个过程中的编译的细节都封装好了,不需要过多的关注,只需要点击运行按钮,就可以直接编译运行了。
上面看到的 . h .h .h、 . c p p .cpp .cpp、 . u i .ui .ui、 . p r o .pro .pro 都是源代码。如果编译运行 Q t Qt Qt 项目,构建过程中,还会产生一些中间文件。

在运行一次程序之后,就会在项目目录并列的位置,生成一个 b u i l d − x x x x x build-xxxxx build−xxxxx 目录,这个目录里面就是该项目在运行过程中,生成的一些临时文件。

三、Qt Hello World 程序
有两种方式,来实现 H e l l o W o r l d Hello\ World Hello World:
- 通过图形化的方式:在界面中创建出一个控件,显示 H e l l o W o r l d Hello\ World Hello World。
- 通过纯代码的方式 :通过编写代码,在界面中创建控件,显示 H e l l o W o r l d Hello\ World Hello World。
1. 使用标签实现
1.1 图形化方式
通过直接拖拽,将 L a b l e Lable Lable 标签添加到界面中,有一个文本框进行编辑,在里面输入 H e l l o W o r l d Hello\ World Hello World。

此时, w i d g e t . u i widget.ui widget.ui 的 x m l xml xml 文件就会多出这样一份代码:
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>130</x>
<y>100</y>
<width>91</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>Hello World</string>
</property>
</widget>
进一步, q m a k e qmake qmake 就会在编译项目的时候,基于这个内容生成一段 C C C++ 代码,通过这个 C C C++ 代码来构建出界面了。(自动完成)
点击运行按钮,就会的得到一个 W i d g e t Widget Widget 的运行窗口:

2.2 纯代码方式
一般通过代码来构造界面的时候,通常会把构造界面的代码放到 W i d g e t Widget Widget(创建项目时自己选的类)的构造函数中。(实现构造函数一般是在 W i d g e t . c p p Widget.cpp Widget.cpp 文件当中编写)
l a b l e lable lable(标签):界面上用来显示内容的字符串控件。
Q t Qt Qt 中更推荐在堆上创建对象( n e w new new 一个对象),创建一个 Q L a b l e QLable QLable 的对象:
此处通过 n e w new new 的方式来创建对象,也就是为了把这个对象的生命周期,交给 Q t Qt Qt 的对象树进行统一的管理(在窗口关闭 / / /销毁的时候把这些对象统一释放)。

#include <QLabel>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QLabel* label = new QLabel(this); // 给这个 label 对象,指定一个“父对象”(对象树)
label->setText("Hello World"); // 隐式类型转换成 QString 对象
}
这里 t h i s this this 指针指向的是 m a i n main main 函数里创建的 W i d g e t Widget Widget 类的对象 w w w:

点击运行按钮,就会的得到一个 W i d g e t Widget Widget 的运行窗口:

此时,就显示出了 H e l l o W o r l d Hello\ World Hello World。(通过代码创建 Q L a b e l QLabel QLabel 默认是在左上角的)
2. 使用输入框实现
2.1 图形化方式
通过直接拖拽,将 L i n e E d i t Line\ Edit Line Edit 标签添加到界面中,有一个文本框进行编辑,在里面输入 H e l l o W o r l d Hello\ World Hello World。
使用编辑框来完成 h e l l o w o r l d hello\ world hello world,分为:
-
单行编辑框: Q L i n e E d i t QLineEdit QLineEdit
-
多行编辑框: Q L i n e T e x t QLineText QLineText
由于这里只需要输入 h e l l o w o r l d hello\ world hello world,因此使用单行编辑框( L i n e E d i t Line\ Edit Line Edit)即可:

点击运行按钮,就会的得到一个 W i d g e t Widget Widget 的运行窗口:

2.2 纯代码方式
同理,把创建 Q L i n e E d i t QLineEdit QLineEdit 控件对象写到 W i d g e t Widget Widget(创建项目时自己选的类)的构造函数中。
w i d g e t . c p p widget.cpp widget.cpp:
#include "widget.h"
#include "ui_widget.h"
#include <QLineEdit>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QLineEdit* line = new QLineEdit(this);
line->setText("Hello World");
}
Widget::~Widget()
{
delete ui;
}
点击运行按钮,就会的得到一个 W i d g e t Widget Widget 的运行窗口(还是默认在左上角):

3. 使用按钮实现
2.1 图形化方式
通过直接拖拽,将 P u s h B u t t o n Push\ Button Push Button 标签添加到界面中,有一个文本框进行编辑,在里面输入 H e l l o W o r l d Hello\ World Hello World。
B u t t o n Button Button 按钮有很多,最常用的就是 P u s h B u t t o n Push\ Button Push Button。

点击运行按钮,就会的得到一个 W i d g e t Widget Widget 的运行窗口:

那为什么按下按钮没有反应呢?
Q t Qt Qt 中的信号槽机制:本质就是给按钮的点击操作,关联上一个函数,用户在点击按钮之后,就会执行这个处理函数。
Q t Qt Qt 中的 c o n n e c t connect connect 函数是 Q O b j e c t QObject QObject 这个类提供的静态函数,这个函数的作用就是连接信号和槽。
在 W i d g e t Widget Widget 类的构造函数中,添加 c o n n e c t connect connect 函数:
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
connect(ui->pushButton, &QPushButton::clicked, this, &Widget::handleClick);
}
其有四个参数:
ui->pushButton:访问到 f o r m f i l e form\ file form file( . u i .ui .ui)文件中创建的控件。(谁发出的信号)
在 Q t D e s i g n e r Qt\ Designer Qt Designer 中创建一个控件的时候,此时就会给这个控件分配一个 o b j e c t N a m e objectName objectName 属性,这个属性的值,要求在界面中得是唯一的(不能和别人重复)。

q m a k e qmake qmake 在预处理 . u i .ui .ui 文件的时候,就会根据这里的 o b j e c t N a m e objectName objectName 生成对应的 C C C++ 代码。 C C C++ 代码中,该 Q P u s h B u t t o n QPushButton QPushButton 对象的变量名字就是这里的 o b j e c t N a m e objectName objectName。

这个 p u s h B u t t o n pushButton pushButton 变量名就是 u i ui ui 属性中的成员变量。
u i ui ui 生成的 u i _ w i d g e t . h ui\_widget.h ui_widget.h 文件:
U i : : W i d g e t Ui::Widget Ui::Widget 继承自 U i _ W i d g e t Ui\_Widget Ui_Widget 类。

w i d g e t . h widget.h widget.h 中 W i d g e t Widget Widget 类的声明:
U i : : W i d g e t Ui::Widget Ui::Widget 类类型的成员变量 u i ui ui 中包含了基类 U i _ W i d g e t Ui\_Widget Ui_Widget 的成员变量 p u s h B u t t o n pushButton pushButton。

因此,在 W i d g e t Widget Widget 类中,就可以通过成员变量 u i ui ui 来访问到 p u s h B u t t o n pushButton pushButton 这个控件了。
-
&QPushButton::clicked:点击按钮的时候就会自动触发这个信号。(发出了个啥信号) -
this:点击操作关联到 W i d g e t Widget Widget 在主函数中创建的对象 w w w 的槽函数上 。(谁来处理这个信号) -
&Widget::handleClick:在 W i d g e t Widget Widget 类中具体实现,接收到点击按钮这个信号之后,通过函数来定义变化的行为。(具体怎么处理)
在 W i d g e t Widget Widget 类中,定义一个处理点击操作的 h a n d l e C l i c k handleClick handleClick 成员函数:
void Widget::handleClick()
{
// 按下按钮,就实现切换文本内容的操作
if(ui->pushButton->text() == QString("Hello World"))
{
ui->pushButton->setText("Hello Qt");
}
else
{
ui->pushButton->setText("Hello World");
}
}
这样就可以实现,点击按钮,从 H e l l o W o r l d Hello\ World Hello World 变到 H e l l o Q t Hello\ Qt Hello Qt:

再次点击,从 H e l l o Q t Hello\ Qt Hello Qt 变到 H e l l o W o r l d Hello\ World Hello World:

2.2 纯代码方式
同理,把创建 Q L i n e E d i t QLineEdit QLineEdit 控件对象写到 W i d g e t Widget Widget(创建项目时自己选的类)的构造函数中。
在 W i d g e t Widget Widget 类中添加一个成员变量 b u t t o n button button:
#include <QPushButton>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
void handleClick();
private:
Ui::Widget *ui;
QPushButton* button; // 定义一个按钮控件 button 的成员变量
};
注意:这里要把 b u t t o n button button 设置为成员变量,因为之后要实现的点击操作的函数中,也需要用到 b u t t o n button button 这个变量,如果只是定义在构造函数这个局部域,则就访问不到按钮,也就无法按钮上的文本进行更换操作。
实现构造函数:
#include <QPushButton>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
button = new QPushButton(this); // 创建按钮这个控件
button->setText("Hello World"); // 设置按钮的文本
// 连接按钮的信号槽操作
connect(button, &QPushButton::clicked, this, &Widget::handleClick);
}
再实现处理点击操作的函数 h a n d l e C l i c k handleClick handleClick:
void Widget::handleClick()
{
// 使用按钮来实现,切换文本的操作
if(button->text() == QString("Hello World"))
{
button->setText("Hello Qt");
}
else
{
button->setText("Hello World");
}
}
这样就可以实现,点击按钮,从 H e l l o W o r l d Hello\ World Hello World 变到 H e l l o Q t Hello\ Qt Hello Qt:

再次点击,从 H e l l o Q t Hello\ Qt Hello Qt 变到 H e l l o W o r l d Hello\ World Hello World:

【总结】
- 对于图形化版本,按钮对象的 n e w new new 操作是 Q t Qt Qt 自动生成的,并且这个按钮对象是 u i ui ui 对象里的一个成员变量,因此无需作为 W i d g e t Widget Widget 的成员。
在实际开发中,如果界面内容是比较固定的,就会使用图形化的方式构造界面。
- 对于纯代码版本,按钮对象是我们自己 n e w new new 的,为了保证其他函数中能够访问到这个变量,就需要把按钮对象设定为 W i d g e t Widget Widget 类的成员变量。
在实际开发中,如果程序界面要经常动态变化,就会使用代码的方式来构造界面。
四、杂项
1. Qt Creator 中的快捷键
在 Q t C r e a t o r Qt\ Creator Qt Creator 中,可以使用一些快捷键,来提升我们使用的效率。
| 快捷键 | 功能 |
|---|---|
| c t r l + / ctrl + / ctrl+/ | 注释 |
| c t r l + R ctrl + R ctrl+R | 运行 |
| c t r l + B ctrl + B ctrl+B | 编译 |
| c t r l + 滚轮 ctrl + 滚轮 ctrl+滚轮 | 字体缩放 |
| c t r l + F ctrl + F ctrl+F | 查找 |
| c t r l + s h i f t + ⬆ / ⬇ ctrl + shift + ⬆/⬇ ctrl+shift+⬆/⬇ | 整行移动 |
| F 1 F1 F1 | 帮助文档 |
| c t r l + i ctrl + i ctrl+i | 自动对齐 |
| F 4 F4 F4 | 同名之间的 . h .h .h 和 . c p p .cpp .cpp 的切换 |
| a l t + e n t e r alt + enter alt+enter | 生成函数声明的对应定义 |
2. qDebug() 打印日志
Q t Qt Qt 中提供了一个 q D e b u g ( ) qDebug() qDebug() 工具,借助这个,就可以帮助我们完成打印日志的过程,很好的处理字符串编码。(不需要程序员关注了,内部帮我们搞好了)
#include <QDebug> // QDebug 是 Qt 中的类,又不会直接使用这个类
#include <iostream>
// 这里是想通过打印日志的方式来证实对象树会在窗口关闭时统一释放对象
~MyLabel()
{
// Windows 下默认编码为 GBK,而 cout 输出的字符串是 utf-8 编码的(因此会乱码)
// std::cout << "MyLabel 被销毁" << std::endl;
qDebug() << "MyLabel 被销毁"; // 自动换行 + 自动处理字符串编码
}
q D e b u g ( ) qDebug() qDebug() 本质是一个宏,封装了 Q D e b u g QDebug QDebug 对象,直接使用 q D e b u g ( ) qDebug() qDebug(),这个东西就可以被当作 c o u t cout cout 来使用。
使用 q D e b u g ( ) qDebug() qDebug() 还有一个好处:打印的调试日志,是可以统一通过编译开关进行一键关闭的。
我们之前调试程序,都是使用调试器,为啥要打印日志进行调试呢?
调试器在很多情况下是有局限性的:一个概率性的 b u g bug bug,只能通过批量的代码(打印日志)才能有效的排查出问题,假如要调试 1 % 1\% 1% 概率出现的 b u g bug bug,不知道要调试多久。
无论哪种方式,本质上都是观察程序执行的中间过程和中间结果。
3. 查询文档的方式
打开帮助文档有三种方式.,实际编程中使用哪种都可以。
- 光标放到要查询的类名 / / /方法名上,直接按 F 1 F1 F1。
比如这里要查询 Q P u s h B u t t o n QPushButton QPushButton 组件中的 s e t T e x t setText setText 方法:

- Q t C r e a t o r Qt\ Creator Qt Creator 左侧边栏中直接用鼠标单击帮助按钮。

- 直接在 A s s i s t a n t 5.14.2 Assistant\ 5.14.2 Assistant 5.14.2 程序中查询。
直接点击索引,输入要查找的控件即可:

4. Qt 坐标系
计算机中的坐标体系:以左上角为原点 ( 0 , 0 ) (0,0) (0,0), X X X 向右增加, Y Y Y 向下增加。(左手坐标系)
给 Q t Qt Qt 的某个控件,设置位置的时候,就需要指定坐标。对于这个控件来说,坐标系原点是相对于父窗口 / / /控件的。


这里创建一个控件 b u t t o n button button 按钮,使用 m o v e ( x , y ) move(x,y) move(x,y) 函数,将其移动到的父窗口 W i d g e t Widget Widget 的 ( 200 , 300 ) (200,300) (200,300) 坐标处。
而 W i d g e t Widget Widget 窗口没有父元素,相当于其父元素就是整个显示器界面,因此,同样通过 m o v e ( x , y ) move(x,y) move(x,y) 函数将其移动到整个显示器界面的 ( 500 , 500 ) (500,500) (500,500) 坐标处。
#include <QPushButton>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QPushButton* button = new QPushButton(this);
button->setText("按钮");
button->move(200,300); // 将 button 控件移动到 (200,300) 位置
this->move(500,500); // 将 Widget 窗口移动到 (500,500) 位置
}

总结
以上就是对 Q t Qt Qt 的初步认识,从 Q t Qt Qt 的发展背景与优势讲述了为什么我们要学习 Q t Qt Qt;也学习了 Q t C r e a t o r Qt\ Creator Qt Creator 的环境搭建和创建项目的操作;以及对系统自动生成的代码所做出的解释;然后还使用三种不同的控件并且分别采用两种方式来实现了 H e l l o W o r l d Hello\ World Hello World;最后,又介绍了 Q t Qt Qt 中的一些小技巧和一些小常识。
更多推荐
所有评论(0)