思维导图
学习目标
这一系列是学习Qt,在C++中,会发现有不少岗位的要求是熟悉Qt,所以Qt的学习是不能推迟的。
一、Qt的概述
1.1 Qt的特点
Qt是一个跨平台的C++应用程序开发框架:
- 具有短平快的优秀特质:投资少,见效快,效益高
- 几乎支持所有的平台,可用于桌面程序开发以及嵌入式开发
- 有属于自己的事件处理机制
Qt是标准C++的扩展,C++的语法在Qt中都是支持的:
- 良好的封装机制使得Qt的模块化程序非常高,可重用性较好,可以快速上手
- Qt提供了一种称为 signals/slots 的安全类型来替代 callback,这使得各个元件之间的协同工作变得十分简单
Qt广泛应用于GUI程序(grapahical user interface),也可以用于非GUI程序
Qt有丰富的API:
- Qt包含多达250个以上的C++类
- Qt可以进行处理正则表达式
Qt支持2D/3D图形渲染,支持OpenGL
OpenGL是很不错的,OpenGL可以做视频渲染,图像/视频编辑以及各种特效,游戏引擎,虚拟现实,3D建模等。
Qt给程序员提供了丰富且详细的官方文档,在Qt软件中也会配有官方文档,不过文档是全英文的
支持XML,JSON
框架底层模板化,使用者可以根据需求选择相应的模块来使用
1.2 Qt的模块
Qt类库中大量的类根据功能分为各种模块,这些模块分为一下几个类型:
- Qt基本模块:提供了Qt在所有平台中的基本功能
- Qt附加模块:实现一些特定功能的提供附加价值的模块
- 增值模块:单独发布的提供额外价值的模块或工具
- Qt工具:帮助应用程序开发的一些工具
模块 | 描述 |
Qt Core | Qt类库的核心,所有其他模块都依赖于这个模块 |
Qt GUI | 设计GUI界面的基础类,包括OpenGL |
Qt Widget | 用于构建GUI界面的C++图形组件类 |
二、Qt的安装(重点)
我们先来点击这个下载路径(Qt下载链接),然后,再按下图进行操作:
三、Qt软件的环境配置
在安装好Qt软件后,我们可以根据下图所示,进入qt软件的一些配置:
四、创建第一个Qt项目
项目文件:一般不需要进行修改。
源文件:
五、Qt中的三个窗口类
5.1 QWidget类型窗口的特点
- 所有窗口类的基类
- 可以内嵌到其他窗口的内部——无边框(需要给该窗口指定父窗口)
- 可以作为独立的窗口显示——有边框(不能给该窗口指定父窗口)
- Qt中所有控件的基类
5.2 QDialog类型窗口的特点
- 对话框窗口类
- 模态和非模态两种显示方式
- 不能进行内嵌
模态和非模态
模态:
在这个状态下,无法进行过窗口的切换,只能先将dialog窗口关闭,才能显示下一个窗口。
Dialog* dig = new Dialog(this); dig->exec(); // 阻塞程序的进行
非模态:
在这种状态下,可以进行窗口的切换
Dialog* dig = new Dialog(this); // 创建对话框 dig->show();
5.3 QMainWindow类型窗口的特点
- 主窗口类
- 可以包含菜单栏,工具栏,状态栏
- 不能进行内嵌
5.4 窗口的显示
5.4.1 内嵌窗口
- 依附于某一个大的窗口,作为大窗口的一部分
- 大窗口就是这个内嵌窗口的父窗口
- 父窗口显示的时候,内嵌的窗口也就被显示出来了
5.4.2 不内嵌窗口
- 这类窗口有边框,有标题栏
- 需要调用函数才可以显示
// Qwidget是所有窗口类的基类,调用这个提供的show()方法就可以显示将任何一个窗口显示出来 void QWidget::show(); // 显示当前窗口和它的字窗口
六、Qt中的坐标体系
6.1 窗口的坐标原点
在Qt中,坐标原点是在左上角。水平从左边向右边延伸,数值增大,为X轴;竖直从上边向下边延伸,数值增大,为Y轴。在图像中,我们可以使用move()函数去执行图像的定位。
6.2 窗口的相对坐标
- 在Qt中的某一个窗口中有可能有若干个控件,这个控件都是嵌套的关系:A窗口包含B窗口,B窗口包含C窗口。
- 每一个窗口都有坐标原点,在左上角,子窗口的位置是基于父窗口的坐标体系来确定的,也就是说通过父窗口左上角的坐标来确定自己的位置
- Qt中窗口显示的时候使用的相对坐标相当于自己的父窗口
- 将子窗口的位置通过父窗口进行移动
// 所有的窗口类的基类:QWidget // QWidget中提供了移动窗口的API函数 // 参数 x, y 是要移动的窗口的左上角的掉,窗口的左上角移动到这个坐标点中 void move(int x,int y); void move(const QPoint &);
举个例子:
// 创建一个按钮 QPushButton* btnA = new QPushButton(this); // 使用move方法,移动按钮的位置 btnA->move(10, 10);
七、Qt中的内存回收机制
在Qt中创建对象的时候会提供一个Parent对象指针(可以查看类的构造函数),下面来解释一下这个parent到底是什么?
QObject是以对象树的形式组织起来,当你创建一个QObject的构造函数时,会看到QObject的构造函数接收一个QObject指针作为参数,这个参数就是parent,也就是父对象指针。这相当于在创建QObject对象时,可以提供一个其父对象,我们创建的这个QObject对象会自动的添加到其父对象的children()的列表中。当父对象析构时,这个列表中的所有对象都会进行析构。
QWidget是能够在屏幕上显示一切组件的父类。QWidget继承于QObject,因此也继承了这种对象树的关系。一个孩子会自动的成为父组件的一个子组件。因此,它会显示在父组件的坐标系统中,被父组件的边界剪裁。例如,当用户关闭一个对话框时,应用程序将其删除,那么,这个对话框中的按钮、图标等会被一起删除。
Qt引入对象树的概念,在一定程度上解决了内存问题:
- 当一个QObject对象在堆上进行创建时,Qt会同时为其创建一个对象树。不过,对象树中对象的创建顺序是没有规律的。这就意味着,这些函数析构的顺序是未定义的。
- 任何一个对象树中的QObject对象在delete的时候,如果这个对象有parent,则自动将其从parent的children()的列表进行删除;如果有孩子,则自动的delete每一个孩子。Qt保证每一个QObject对象不会被析构两次,这是由析构顺序决定的。
综上所述,我们可以得出一个结论:Qt有内存回收机制,但是并不是所有被new的对象被自动回收,满足条件才可以被回收。
需要满足下面两个条件:
- 创建的对象必须是QObject类的子类(间接子类也可以)。
- QObject类是没有父类的,Qt中有一大部分类都是从这个类派生出去的,Qt中使用频率很高的窗口类和控件都是QObject的直接或间接子类
- 创建出来的类必须要指定其父对象是谁,一般情况下有两种操作方式:
// 方法一:通过构造函数 // parent:当前窗口的父对象,找出构造函数中的parent参数即可 QWidget::QWidget(QWidget * parent = Q_NULLPIR, Qt::WindowFLAGs f = Qt::WindowFlags()); QTimer::QTimer(QObject * parent = nullptr); // 方法二:通过setParent()方法 // 假设这个控件没有在构造的时候指定父对象,可以调用QWidget的api指定父窗口对象 void QWidget::setParent(QWidget* parent); void QObject::setParent(QObject* parent);