文章目录
- Qt是什么
- Qt的优点
- Qt开发环境的基本使用
- 对象树
- 其他控件
- 输入框
- 按钮
本篇总结的是对于Qt框架的基本认识
Qt是什么
Qt框架是一个跨平台的C++图形用户界面应用程序框架,框架是一群大佬发明出来的,帮助新手使用的一个内容,如果没有框架的存在,那么就容易出错,而有了框架的存在,就是限制普通的新手程序员的自由,来帮助新手去进行使用
Qt的优点
- Qt跨平台,几乎支持所有的平台
- 接口简单,容易上手,学习Qt框架对于学习其他框架来说也有很重要的意义
- 一定程度上简化了垃圾回收机制
- 开发效率比较高,可以快速构建一个应用程序
- 有比较好的市场氛围
- 可以进行嵌入式开发
Qt开发环境的基本使用
对于Qt开发来说,使用的一个开发的环境是Qt Creator,那对于这个环境来说,下面讲述一下基本的使用方式和对应的选项意义
首先是创建一个项目,直接进行新建即可
那对于新建之后的选项,就有不同的类型了,这里由于是初学,所以只选择一个基础的选择,如果想要用Qt去完成一个GUI程序,那么就要选择第一个选项,对于下面的选项也进行注释和备注:
接着会有下面的界面
那么这个里面包含的这三项是什么呢?
这是一个构建系统,通过Qt写的程序,会涉及到一系列的元编程技术,也就是说用代码来生成代码
那Qt框架在进行编译的时候,会自动调用一系列的生成工具,基于用户本身写的代码,生成一系列的其他的C++的代码,最终进行编译的代码,其中也包含了这些最后生成的这些代码,这就是构建系统
那在上面的这三种中,其中qmake是一个老牌的Qt构建工具,而CMake并非是Qt的专属构建工具,许多开源项目中都会用到CMake,而最后的Qbs是一个新一代的构建工具,但是对于现在来说,使用的场景比较少
再下一个是这一步:
上图所示的是,当使用Qt Creator创建项目,会自动的生成一些代码出来,而此时这个生成的代码中就会包含一个基本的列,而在这个界面选项中要选择的就是一个自动生成的类的父类是什么
- QMainWindows:这个类可以生成一个完整的应用程序窗口,包含有菜单栏,工具栏,状态栏等
- QWidget:这个类表示一个控件,也就是窗口上的一个具体的元素,例如有输入框,按钮,下拉框,单选按钮,复选按钮等等
- QDialog:这个类表示的是一个对话框
在Qt页面中,内置的类都是用Q前缀开头来表示的
关于form file:
这个form file在Qt框架中扮演者非常重要的角色,Qt中创建图形化界面的程序主要有以下两种方式:
- 直接通过C++代码的方式进行创建界面
- 通过form file,用图形化的方式来生成界面,此时就可以通过这个Qt Designer或者直接使用Qt Creator来编辑这个ui文件,从而用图形化的方式快速的方便的创建出这个图形界面
再之后就是关于基于哪个编译器进行构建后续代码
对象树
我们创建一个项目,初步使用一下QT框架:
在这个项目中创建了一个标签,并且写入了一个内容,那么此时进行运行出结果为:
此时,的确运行出了一个标签,上面打印的是我们想要的内容,那么这也就意味着初步实现了目的,但是是否有这样的问题:
new的对象,难道不会导致内存泄漏吗?
事实上,这个问题是存在的,但是在QT框架中已经解决了这个问题,具体的解决措施就是对象树:
#include "widget.h"
#include "ui_widget.h"
#include <QLabel>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QLabel* label = new QLabel(this);
label->setText("hello world");
}
Widget::~Widget()
{
delete ui;
}
那么解决的方式就是,new的时候把this传递进去了,也就是说是把整个对象的生命周期统一交给了这个QT对象树来进行管理,所以在这个代码中,QT的控制下是不会造成内存泄漏的,label对象会在合适的时候进行析构,因为这个对象已经在对象树上了
那么什么是对象树呢?
在前端开发当中,也会有这样的对象树的概念,DOM本质上就是一个树形结构,也就是所谓的N叉树,通过树形结构把界面上的元素组织起来,而在QT中也是这样的道理,具体的可以用下面的图来进行表示
实验验证
所以下一步,我们就创建对应的实验过程来验证析构的过程:
// mylabel.h
#ifndef MYLABEL_H
#define MYLABEL_H
#include <QLabel>
class MyLabel : public QLabel
{
public:
MyLabel(QWidget* parent);
~MyLabel();
};
#endif // MYLABEL_H
// mylabel.cpp
#include "mylabel.h"
#include <iostream>
MyLabel::MyLabel(QWidget* parent) : QLabel(parent)
{
}
MyLabel::~MyLabel()
{
std::cout << "MyLabel delete" << std::endl;
}
运行结果如下:
在关闭框后,就会打印出这个日志信息,说明的确已经把信息析构了
在QT中,存在专门打印调试信息的类,这里演示其中的一个用法,它也可以用来处理中文:
其他控件
输入框
下面介绍一种使用输入框来显示hello world的方式
这种比较简单,就不再贴代码了
按钮
这里我们使用一个pushbutton,也就是普通按钮,来显示hello world
添加后,运行确实可以显示出结果
但是遗憾的是,点这个按钮没有任何回显,这不符合按钮的设计初衷,因此就引入了信号与槽的概念,这里只讲述最基本的理解:就是可以点击这个按钮后,去执行一个新的函数
这里首先引入一个函数,connect,对于这个函数来说并不陌生,它和Linux中的socket中的connect有些类似,但也不太一样,具体看用法:
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
connect(ui->pushButton, &QPushButton::clicked, this, &Widget::Handler);
}
Widget::~Widget()
{
delete ui;
}
void Widget:: Handler()
{
if(ui->pushButton->text() == QString("hello world"))
ui->pushButton->setText("hello Qt");
else
ui->pushButton->setText("hello world");
}
如上所示,即可实现一个切换按钮显示内部文字的功能:
点击前:
点击后:
那这是如何做到的呢?
先看一下这个connect函数:
connect(ui->pushButton, &QPushButton::clicked, this, &Widget::Handler);
这一行的信息是代表了什么意思呢?
简单来说,第一个参数的意思是谁发出的信号,第二个参数意思是发出了什么信号,第三个参数意思是谁来处理这个信号,第四个参数意思是怎么来进行处理
结合到上面这个例子,我们可以看出的结论是,这个函数表示的意思是说,让ui指针指向的按钮对象可能会发出信号,发出的信号是一个点击信号,这个信号让当前对象来进行处理,处理的方式是执行Handler函数,这就是上面这个的基本意思
那么我们该如何理解这个流程呢?
首先要理解,ui是什么,这个->是在做什么?
这个过程本质上就是在访问到form file当中所创建的控件,具体如下所示:
在QT创建一个控件的时候,就会给这个控件分配一个Name的属性,这个属性的值在整个页面当中是唯一的,而在qmake进行预处理的时候,就会根据这里的名字来进行对应的C++代码的生成
而当这个按钮被点击的时候,本质上就会找到这个按钮的名字,然后进行识别
而在使用自动化构建工具构建时,就会依据这个Name,然后生成具体的内容:
在objectName当中,设置的是什么值,具体的就会生成的变量是什么值,之后就会通过这个变量来获取到对应的空间的变量了