目录
3-6:如何理解QT_BEGIN_NAMESPACE和QT_END_NAMESPACE这两个宏
1、新建工程
Qt Widgets Application模板会创建一个传统的桌面应用程序,包括窗口和用户界面元素的基础代码。
Qt Console Application模板提供了一个简单的控制台应用程序框架,适用于不需要图形用户界面的应用程序。
Qt Quick Application模板则适合需要使用QML来创建现代、流畅动画和触摸友好界面的项目。
选择模板后,Qt Creator会自动生成一些基础代码文件和资源,这样就可以直接开始添加特定的功能和逻辑,而不是从零开始。这个过程既节省时间,又确保了项目的初始结构符合Qt的最佳实践。
基于小部件的Qt应用程序:指的是使用Qt框架开发的桌面应用程序,它由多个可交互的界面元素(小部件)组成。Qt框架提供了一套丰富的标准小部件,比如按钮、文本框、滑块等,开发者可以通过组合这些小部件来构建复杂的用户界面。
这个过程可以把它想象成搭积木。每个小部件就像是一个积木块,你可以选择不同的积木块(按钮、文本框等),按照一定的布局方式拼凑在一起,最终搭建出一个完整的应用程序界面。而Qt Designer则提供了一个可视化的界面,让你可以直观地拖拽小部件到窗口中,方便地设计和调整界面布局,无需手写太多代码。
“此向导生成一个Qt Widgets Application项目。应用程序默认派生自QApplication,并包括一个空白小部件。”
即在使用这个向导(一个帮助你步步创建项目的工具)创建一个Qt Widgets应用程序时,它会自动创建一个基础的程序框架给你。这个框架就像是一个初始的空房间,等待你按照自己的想法来装修。“应用程序默认派生自QApplication”意味着,这个程序是建立在Qt框架中的一个基本组成部分QApplication之上的。你可以把QApplication想象成房子的基础,它提供了电、水和煤气——也就是程序运行所必需的一些基础设施和服务。 “包括一个空白小部件”则意味着,在这个房子的基础上,向导还为你准备了一个空房间(一个空白小部件)。小部件在Qt中就像是房间里的家具一样,是用户可以看到和操作的界面元素,比如按钮、文本框等。但这里的小部件是空的,也就是说,它是一个没有添加任何家具(界面元素)的房间,等待你按照需要来添加和设计。
简单来说,这句话的意思就是:向导帮你搭建了一个有基础设施的房子和一个空房间,现在等你来按自己的想法装修和填充内容了
什么是QApplication?
QApplication是Qt框架中的一个核心类,用于管理GUI应用程序的控制流和主要设置。简而言之,它是每一个基于Qt的图形界面应用程序(GUI application)的启动点。当你开发一个Qt应用程序时,你通常会在程序的main函数中创建一个QApplication的实例。
QApplication负责许多基本的系统级别的事务,包括:
初始化应用程序与图形显示系统的通信。
管理事件循环,事件循环是GUI程序的心脏,负责接收和分发事件,例如鼠标点击或按键事件。
处理应用程序的全局设置,比如字体和调色板,以确保应用程序在不同平台上具有一致的外观和感觉。
使应用程序能够处理命令行参数。
在Qt的世界里,没有QApplication的实例,GUI应用程序就无法正常运行。它为应用程序提供了必要的环境和管理功能,确保应用程序能够以图形界面的形式与用户交互。简单来说,如果将一个GUI应用程序比作一场戏剧,QApplication就是导演,它负责幕后的所有准备工作,确保演出可以顺利进行。
在创建QT工程时,“Define Build System”(定义构建系统)的意思是指定用于编译和链接应用程序的工具和流程。构建系统负责将你的源代码(如C++文件)转换成可执行程序或库。
构建系统就像是一个厨师,源代码就像是食材,而最终的可执行程序或库就像是做好的菜。你需要告诉厨师(构建系统)如何使用这些食材(源代码),比如烹饪的顺序、使用哪些工具(编译器、链接器等),以及是否需要添加一些特殊的调料(编译选项、宏定义等),来制作出你想要的菜(程序)。
在QT中,常见的构建系统包括qmake和CMake等。选择合适的构建系统,可以帮助你更高效地管理项目的编译和链接过程。
"translation"选项:涉及的翻译不仅限于代码中的文字或字符串。它实际上是指将应用程序界面(如按钮标签、菜单项、对话框文本等)中出现的文本翻译成不同的语言,而不需要改变程序的源代码。这意味着,你可以创建一个应用程序,然后通过添加不同的翻译文件,让这个应用程序支持多种语言,以适应不同地区的用户。
构建套件(Kits):选择用于编译和运行项目的构建套件。这取决于你的目标平台和开发需求,比如是否是桌面应用、Android应用等。
什么是构建套件:
一个构建套件在Qt Creator中定义了编译和运行Qt应用程序所需的一组设置和工具,包括编译器、Qt版本、设备类型(如桌面、移动设备)、调试器以及其他可能需要的设置或工具。可以把构建套件想象成一个完整的工作台,它包含了你需要的所有工具和材料来构建和测试你的项目。比如,如果你想在Windows系统上开发桌面应用,你需要的工作台(构建套件)可能包括一个特定版本的Qt库、一个适用于Windows的编译器(如MSVC或MinGW),以及其他一些工具和设置。
选择正确的构建套件很重要,因为不同的目标平台和开发需求可能需要不同的工具和配置。例如,开发一个用于Android设备的移动应用,你需要的构建套件就会包括Android SDK、特定的编译器和一些用于Android开发的特定设置。
2、新建一个“Diss 谢帝”的标签
创建完成后,在窗口的左侧显示项目文件(分别包含头文件、源文件、界面文件)。如果选择的是CMake构建即为CMakeLists.txt ; qMake构建则为.pro文件。(即是对工程的描述文件)
双击界面文件下的wdiget.ui,则会弹出下面UI设计界面。
选择Display下的Label,直接拖入主窗口中,双击进行编辑,也可以通过右侧①处的表格界面进行编辑。编辑后的结果如下图所示。
点击左下角的运行标签,即可弹出一个界面窗口,即本次实验所要完成的目标。
3、补充内容:
3-1:更改标签字体属性
在右下角属性栏中,点击font(字体)栏中的三个小点,弹出如下窗口,可设置字体的类型、风格、大小等参数。
3-2:什么是GUI
是“Graphical User Interface”(图形用户界面)的缩写。GUI是指允许用户通过图形标识(如窗口、图标、按钮和滑动条等)而非仅通过文本命令与程序交互的界面。这种界面设计让用户操作变得直观易懂,极大地提高了软件的可用性和访问性。
3-3:什么是命名空间?
命名空间是C++中的一个特性,用于解决命名冲突的问题。可以把它想象成一个文件夹系统在你的电脑上。在不同的文件夹(命名空间)中,可以有同名的文件(函数、类名等),而这些文件夹的名字帮助区分同名文件的身份。在C++编程中,命名空间允许你组织代码的方式,使得即使在大型项目中,函数或类的名字相同也不会发生冲突。
3-4:什么是命名空间的宏?
在Qt中,QT_BEGIN_NAMESPACE
和QT_END_NAMESPACE
是两个宏,用于包裹Qt框架内的代码声明。Qt使用这些宏来提供一个额外的命名空间层级,以防止其内部的命名与用户的代码或者其他库发生冲突。它们相当于在代码的一部分外围加上了一个命名空间的声明和结束,但这个命名空间的名字是基于Qt配置的,可以是Qt
或者其他名称,这取决于Qt是如何被构建的。
3-5:什么是前向声明?
前向声明是在C++中声明类、函数或变量的方式,但不定义它。通过前向声明,你告诉编译器有一个指定名称和类型的实体将在程序的其他地方被定义。这样做的好处是可以减少编译时间和避免头文件的循环依赖问题。例如,在Qt中:
namespace Ui { class Widget; }
这里的class Widget;
就是一个前向声明,告诉编译器将会有一个名为Widget
的类在某处定义,而且它位于Ui
这个命名空间中。这允许在代码其他部分提前使用Ui::Widget
类型的指针或引用,即使Widget
类的完整定义还未被引入。
3-6:如何理解QT_BEGIN_NAMESPACE和QT_END_NAMESPACE这两个宏
想象一下,Qt是一个巨大的图书馆,里面有成千上万的书籍(即代码)。为了让大家更容易找到自己需要的书籍,图书馆被划分成了许多不同的区域(即命名空间)。这样,即使有两本名字相同的书,只要它们在不同的区域,大家就不会混淆。
但是,这个图书馆(Qt)非常特别,它允许你根据自己的需要,稍微调整某些区域的名称。QT_BEGIN_NAMESPACE
和QT_END_NAMESPACE
就像是图书馆给你的两个魔法工具,允许你在放置你的书籍(代码)之前和之后,声明“从这里开始,到这里结束,我要把我的书放在一个特别的区域里”。这样做的目的是为了确保,即使你的书籍(代码)的名字与图书馆里已有的书籍相同,它们也不会被混淆,因为它们位于不同的区域(命名空间)。
4、项目文件详解
sample1_1.pro文件:
.pro
文件是一个项目文件,用于定义项目的构建配置。它是由Qt的构建系统(qmake)读取的,用来指导如何编译和链接程序。.pro
文件包含的内容可以分为几个部分:
-
项目信息:比如项目类型(应用程序、库等)、项目名称。
-
源文件和头文件:列出项目中使用的所有
.cpp
源文件和.h
头文件,告诉构建系统哪些文件需要被编译。 -
界面文件:对于使用Qt Designer设计的图形界面,
.pro
文件会包含这些.ui
文件的列表。 -
资源文件:项目中使用的资源文件(如图片、翻译文件等)列表。这些资源会被编译到程序中,使得程序运行时可以访问这些资源。
-
库依赖:如果项目依赖于其他库(无论是Qt自带的库还是第三方库),这些依赖会在这里声明。这告诉构建系统需要链接哪些库文件。
-
构建配置选项:比如编译器标志、定义宏等,这些选项可以调整构建过程,优化生成的程序。
简单说,.pro
文件就像是建造一栋房子的蓝图。它告诉建造者(也就是构建系统)房子的设计(项目信息),使用了哪些材料(源文件、头文件、资源文件等),需要哪些工具和材料来完成(库依赖),以及如何组合这些材料(构建配置选项)来建造出最终的产品(可执行文件或库)。通过阅读这个蓝图,构建系统能够理解如何从这些文件和资源中,按照给定的指令构建出最终的应用程序或库。
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#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
第1行,将core和gui模块添加到QT中。
第3行,这行是一个条件语句,检查Qt的主版本号是否大于4。如果是(意味着使用的是Qt 5或更高版本),则将Widgets模块添加到项目中。这是因为在Qt 5中,许多界面元素被移到了Widgets模块。
第5行,这行指示qmake使用C++17标准来编译项目。CONFIG
变量用于控制项目的各种配置选项。
第11行,定义了项目的源代码文件。" \ " 表示换行。
第15行,定义了项目的头文件。
第18行,定义了项目中使用的Qt Designer表单文件。FORMS
变量包含了.ui
文件的列表,这些文件可以通过Qt Designer编辑,并且在构建时会被转换成相应的C++代码。
第22行,这行是一个条件赋值,仅当目标平台是QNX时生效,它设置了二进制文件的安装路径为/tmp/$${TARGET}/bin
。$${TARGET}
是一个变量,代表项目名称。
第23行,这行是上一个条件的扩展,针对非Android的Unix系统(如Linux),设置二进制文件的安装路径为/opt/$${TARGET}/bin
。在Unix-like系统上(不包括Android),设置编译后的应用程序或库的安装路径为/opt/项目名称/bin
。
第24行,检查target.path
是否已设置,如果是,则将target
(代表构建的目标)添加到INSTALLS
变量中。INSTALLS
变量用于定义安装规则,qmake可以利用这些规则来生成安装或卸载项目文件的make目标。“ : ”
后面跟着的是当条件表达式为真(即target.path
不为空)时要执行的操作
widget.h文件:
widget.h
是一个头文件,它定义了一个或多个窗口小部件(Widgets)的类。头文件在C++中用来声明类的结构、函数原型、变量、宏定义等,而不包含这些函数的实际实现代码(实现代码通常放在对应的.cpp
文件中)。
#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
第4行:#include <QWidget> :引入需要的Qt模块和其他头文件,比如#include <QWidget>,这样你就可以使用Qt框架提供的QWidget类的功能来创建你的窗口小部件。
第6-10行:这几行定义了一个名为Ui
的命名空间,其中声明了一个前向声明的Widget
类。 QT_BEGIN_NAMESPACE
和QT_END_NAMESPACE
是Qt用来处理命名空间的宏,确保Qt库的命名空间与用户代码中可能存在的命名空间不会发生冲突。这里的Ui::Widget
通常是由Qt Designer自动生成的界面类的前向声明,用于声明一个界面类,该类在相应的.ui
文件中定义。
命名空间,命名空间的宏,前向声明的定义见3-3到3-5
第12行:class Widget : public QWidget :声明了一个名为Widget的类,它继承自QWidget。这意味着Widget类是一个Qt窗口小部件,拥有QWidget的所有功能。
第14行:Q_OBJECT :Q_OBJECT宏在类的私有部分被定义,它启用了Qt的元对象系统,包括信号与槽的机制,以及Qt的其他一些反射机制。这一宏是使用Qt信号和槽必须的。
第17~18行:这里定义了Widget类的构造函数和析构函数。构造函数接受一个指向父窗口小部件的指针,默认为nullptr,表示这个窗口小部件没有父窗口小部件。析构函数用于在删除窗口小部件时进行清理工作。
第21行:Ui::Widget *ui :这行代码声明了一个指向Ui::Widget
类的指针ui
。Ui::Widget
类是由uic工具(基于.ui
文件)自动生成的,并且负责设置和管理这个窗口小部件的用户界面。这使得开发者可以通过Qt Designer来设计界面,而不必手动编码。即ui是一个存放地址的指针变量,而这个地址所指向的内容是一个Widget类。
widget.cpp文件:
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
如何正确理解Widget::Widget(QWidget *parent) :QWidget(parent) 这句代码?
第4~6行是Widget构造函数的实现。定义了Widget
类的一个构造函数,这个构造函数接受一个可选的QWidget
类型的指针作为父窗口(默认为nullptr
),用于初始化这个Widget
对象的基类部分(QWidget
)和成员变量(ui
)。
Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget)
- 第一个
Widget
指的是类名。 - 第二个
Widget
(紧跟在::
之后的那个)指的是这个类的构造函数。 Widget::Widget
表示这是Widget
类的构造函数,而::
是C++中的作用域解析操作符,用于指明紧随其后的成员属于哪个类。-
: QWidget(parent)
是初始化列表的第一部分,它调用了Widget
类的基类QWidget
的构造函数,传入了parent
参数。这个调用确保了Widget
作为QWidget
的派生类,其基类部分被正确初始化。 -
, ui(new Ui::Widget)
紧跟在后面,是初始化列表的第二部分,用逗号与前一项分隔。这部分负责初始化Widget
类中的ui
成员变量。ui
是一个指向Ui::Widget
类型的指针,Ui::Widget
是由Qt的用户界面编译器(uic)根据.ui
文件自动生成的类,用于管理和设置UI。这里通过调用new Ui::Widget
创建了一个Ui::Widget
的实例,并将指针赋值给ui
。注:ui是在widget.h里面的Widget类中定义的成员变量,是一个指向Ui::Widget的指针。
-
逗号“
,
”表示连续的初始化操作;“ :”表示初始化操作,即在实现{ }括号内的代码前先执行的操作,这里执行了两个操作,第一个是调用了QWidget类的初始化函数,第二个是在堆区(heap)创建了一个Ui::Widget
类的实例,并返回了一个指针,并赋值给ui。圆括号( )
用于将new Ui::Widget
表达式的结果,也就是一个指向Ui::Widget
对象的指针传递给ui
成员变量。 -
第一个
parent
是Widget
构造函数的输入参数,允许指定这个Widget
的父对象。而第二个parent
则是将这个输入参数直接传递给QWidget
基类的构造函数,以确保基类部分也接收到了父对象信息
第8行,ui
是指向Ui命名空间中的Widget
类的实例的指针,该类是由Qt的用户界面编译(uic)根据.ui
文件自动生成的。(但仅仅有这个类的定义还不足以让界面显示出来,这就需要通过new Ui::Widget来创建一个实例).ui
文件是通过Qt Designer创建的图形界面的XML描述文件。
ui->setupUi(this);
这行代码的作用是初始化和设置由Qt Designer设计的用户界面。它调用了ui
对象的setupUi
方法,将当前的Widget
对象(通过this
指针表示)作为参数。通过传入this
指针,setupUi
确保所有界面元素都将当前的Widget
对象作为它们的父对象。
将鼠标指针指导setupUi上,按住ctrl,单击鼠标左键进入成员函数如下图所示。这个文件中的UI_Widget类是由.ui
文件自动生成的,通过初始化函数ui(new Ui::Widget),将此实例化。详细阅读方框中的代码即可理解图形化设计是如何与代码联系起来的,这里不做详细介绍。
通过在代码中修改标签属性,编译之后即可显示。