31. Qt 插件机制
-
Qt 的插件机制是一种将应用程序的功能模块化的方法
- 通过使用 Qt 的插件机制,可以将应用程序的一些功能打包成独立的插件,这些插件可以在运行时动态加载和卸载,从而实现应用程序的可扩展性和灵活性
- 插件可以是动态链接库或静态链接库,包含了一些特定的功能
- Qt 提供了 QPluginLoader 类和 QFactoryInterface 类用于管理插件。通过插件,可以将应用程序的功能分解为多个独立的部分,方便开发和维护
- 使用 QPluginLoader 类动态加载插件,并通过调用 QPluginLoader 的 instance() 方法获取插件实例
-
常见插件类型
- 运行时插件(Runtime Plugins)
- 这种插件是动态链接库(.dll/.so文件),可以在应用程序运行时被动态加载。运行时插件主要用于添加新的功能、视图、或者处理逻辑到应用程序中
- 设计时插件(Designer Plugins):这种插件用于扩展 Qt Designer 的功能,使其能够支持各种自定义的控件或部件。
- 软件插件(Non-Graphical Plugins):这种插件通常用于处理非图形化的任务,例如数据库插件或文档处理插件
- 运行时插件(Runtime Plugins)
32. QPainter 绘图和 QChart 图表绘制
32.1 QPainter 绘图
- Qt 二维绘图基本功能是使用 QPainter 在绘图设备(QWidget、QPixmap、QPrinter 等)上绘图
- QWidget 是最常见的绘图设备,所有的界面组件都是从 QWidget 继承而来的,界面组件的显示效果实际上是 QPainter 在 QWidget 上实现的
- QPainter 可以在 QWidget 上绘制出自定义的组件形状和实现特定的显示效果,这也是设计自定义界面组件的基础
- 用 QPainter 在绘图设备上绘图主要是指用 QPainter 的接口函数绘制各种基本图形,包括点、直线、圆、矩形、多边形、文字等。图形的线条特性、颜色特性、文字特性由以下 3 个类的特性决定
- OPen 类:用于控制线条的颜色、宽度、线型等
- QBrush 类:用于设置一个区域的填充特性,包括填充颜色、填充样式、渐变特性等,还可以采用图片进行材质填充
- QFont 类:用于设置文字的字体、样式、大小等属性
- 坐标变换
32.2 QChart 图表绘制
- Qt Charts 是 Qt 自带的图表库,用于绘制各种类型的图表,例如曲线图、饼状图、柱形图、折线图等,使用 Qt Charts 可以方便地将数据可视化,并支持用户交互和定制化设
- 曲线图用于展示一段时间内某个变量的变化趋势,例如温度、湿度、压力等
- 饼状图用于展示不同数据之间的比例关系,例如不同国家的 GDP 占比、不同产品的销售占比等
- 柱形图用于展示不同数据之间的数量关系,例如不同月份的销售额、不同省份的人口等
- 折线图用于展示不同数据之间的趋势变化,例如不同时间段内的股票价格、不同季度的 GDP 增长率等
- 示例:QChart 绘制曲线图
// 创建 QChart 对象,并设置标题和坐标轴 QChart *chart = new QChart(); chart->setTitle("Temperature"); chart->legend()->hide(); chart->createDefaultAxes(); // 创建 QLineSeries 对象,设置曲线的名称和数据 QLineSeries *series = new QLineSeries(); series->setName("Temperature"); series->append(0, 20); series->append(1, 22); series->append(2, 24); series->append(3, 26); // 将 QLineSeries 对象添加到 QChart 对象中 chart->addSeries(series); // 创建一个 QChartView 对象,并将 QChart 对象设置为其父对象 QChartView *chartView = new QChartView(chart); chartView->setRenderHint(QPainter::Antialiasing); // 将 QChartView 对象添加到布局中 ui->chartLayout->addWidget(chartView);
33. Qt 图形视图架构(Graphics View)
采用 QPainter 绘图时需要在绘图设备的事件处理函数 paintEvent() 里编写代码来实现绘图,用这种方法绘图如同使用 Windows 的画图软件绘图,绘制的图是位图
- Qt 为绘制复杂的可交互的图形提供了图形/视图(graphics/view)架构,这是一种基于图形项的模型/视图结构
- 使用图形/视图架构,可以绘制复杂的由成千上万个基本图形组件组成的图形,并且每个图形组件是可选择、可拖放和可修改的,类似于矢量绘图软件的绘图功能
33.1 场景、视图与图形项
-
图形/视图架构主要由 3 个部分组成
-
1. 场景
- QGraphicsScene 类提供绘图场景(scene),它的父类是 QObject,场景不是界面组件,它是不可见的
- 场景是一个抽象的管理图形项的容器,可以向场景添加图形项,可以获取场景中的某个图形项
- 场景主要具有如下功能
- 提供管理大量图形项的快速接口
- 将事件传播给每个图形项
- 管理每个图形项的状态,例如选择状态、焦点状态等
-
2. 视图
- QGraphicsView 是图形/视图架构中的视图组件,QGraphicsView 的间接父类是 QWidget,所以它是一个界面组件,用于显示场景中的内容,可以为一个场景设置多个视图,用于对同一个场景提供不同的显示界面
- 默认情况下,当视图大于场景时,场景在视图的中央位置显示
-
3. 图形项
- 图形项就是一些基本图形组件,所有图形项类都是从 QGraphicsItem 继承而来的,而 QGraphicsItem 没有父类
- 一个图形项存储了绘制这个图形项的各种参数,场景管理所有图形项,而视图组件则负责绘制这些图形项
33.2 图形/视图架构坐标系
- 图形/视图架构有 3 个有效的坐标系:场景坐标系、视图坐标系、图形项坐标系
- 场景坐标系等价于 QPainter 的逻辑坐标系,一般以场景的中心为原点
- 视图坐标系与绘图设备坐标系相同,是物理坐标系,默认以左上角为原点
- 图形项坐标系是局部逻辑坐标系,一般以图形项的中心为原点
34. QImage 图像处理
- QImage 和 QPixmap 是用于图像显示和处理的绘图设备类
- 可使用 QPixmap 加载图片文件或图片数据,然后在 QLabel 组件上显示图片,QPixmap 主要用于在界面上显示图像,可以对图像进行缩放,但不能像 QImage 那样对图像进行像素级的处理
- QImage 可以访问图像中每个像素的颜色数据,适用于需要对图像数据进行处理的应用,例如:可用于旋转或翻转图像,改变图像亮度或对比度等
35. Qt 模型/视图/代理结构(MVD)
35.1 概述
- 模型/视图结构是一种将数据存储和界面展示分离的编程方法
- 模型存储数据,视图组件显示模型中的数据,在视图组件里修改的数据会被自动保存到模型里
- 模型的数据来源可以是内存中的字符串列表或二维表格型数据,也可以是数据库中的数据表,一种模型可以用不同的视图组件来显示数据
35.2 组成
- 1. 源数据(data)
- 是原始数据,如数据库的一个数据表或 SQL 查询结果、内存中的一个字符串列表或磁盘文件系统结构等
- 2. 视图(view)
- 也称为视图组件,是界面组件,视图从模型获得数据然后将其显示在界面上
- Qt 提供一些常用的视图组件,如 QListView、QTreeView 和 QTableView 等
- 3. 模型(model)
- 也称为数据模型,与源数据通信,并为视图组件提供数据接口。它从源数据提取需要的数据,用于视图组件进行显示和编辑
- Qt 中有一些预定义的模型类,如 QStingListModel 是字符串列表的模型类,QSqlTableModel 是数据库中数据表的模型类
- 4. 代理(delegate)
- 在视图与模型之间交互操作时提供的临时编辑器
- 模型向视图提供数据是单向的,一般仅用于显示,当需要在视图上编辑数据时,代理会为编辑数据提供一个编辑器,这个编辑器获取模型的数据、接受用户编辑的数据后又将其提交给模型
- 例如在 QTableView 组件上双击一个单元格来编辑数据时,在单元格里就会出现一个 QLineBdit 组件,这个编辑框就是代理提供的临时编辑器
模型、视图和代理通过信号和槽进行通信
- 当源数据发生变化时,模型发射信号通知视图组件
- 当用户在界面上操作数据时,视图组件发射信号表示操作信息
- 在编辑数据时,代理会发射信号告知模型和视图组件编辑器的状态
35.3 核心概念
-
模型常见的 3 种展示形式
- 列表模型(list model)、表格模型(table model)、树状模型(tree model)
- 模型中存储数据的基本单元都是项(item),每个项有一个行号和一个列号,还有一个父项(parent item),3 个模型都有一个隐藏的根项(rootitem)
-
自定义代理
- 若要替换 QTableView 组件提供的默认代理组件,就需要为 QTableView 组件的某列或某个单元格设置自定义代理
- 自定义代理类需要从 QStyledItemDelegate 类继承,创建自定义代理类的实例后,再将其设置为整个视图组件或视图组件的某行或某列的代理,以替代默认代理的功能
36. Qt 的 MVC 架构和 MVD 架构区别
- MVC 架构(Model-View-Controller)
- Model(模型):负责存储应用程序的数据,并提供对数据的访问和操作接口
- View(视图):负责显示模型中的数据给用户,并接收用户交互事件
- Controller(控制器):负责处理用户操作和更新模型的数据,是用户输入和模型之间的桥梁
- MVD 架构(Model-View-Delegate)
- Model(模型):同样负责存储应用程序的数据,提供数据的访问和操作接口
- View(视图):负责显示模型中的数据给用户,但不处理用户交互事件,而是通过 Delegate 来处理
- Delegate(委托):负责处理用户的交互事件,比如用户的点击、编辑等操作,并更新模型的数据
Controller 更多是负责业务逻辑的部分,而 Delegate 更多是处理用户界面的交互逻辑
37. Qt 双缓冲机制
- 双缓冲机制是指在绘制控件时,首先将要绘制的内容绘制在一个图片中,再将图片一次性地绘制到控件上(一个用于绘制,一个用于显示)
- 在早期的 Qt 版本中,若直接在控件上进行绘制工作,则在控件重绘时会产生闪烁的现象,控件重绘频繁时,闪烁尤为明显,双缓冲机制可以有效地消除这种闪烁现
- 双缓冲机制虽然可以避免闪烁等问题,但是也会增加内存的消耗
- 双缓冲机制在很多场合有用
- 当所需绘制的内容较复杂并需要频繁刷新
- 者每次只需要刷新整个控件的一小部分时
- 双缓冲机制的实现过程
- 1、创建两个缓冲区,一个用于绘制,一个用于显示
- 2、在绘制过程中,将所有的绘制操作都先绘制到绘制缓冲区中
- 3、绘制完成后,将绘制缓冲区中的内容复制到显示缓冲区中
- 4、显示缓冲区中的内容会被显示在屏幕上
- 这样,由于绘制操作是在绘制缓冲区中进行的,因此不会直接影响到显示缓冲区中的内容,从而避免了闪烁等问题
- 双缓冲机制是由 QPainter 类和 QWidget 类共同实现的,QPainter 类用于在绘制缓冲区中进行绘制操作,而 QWidget 类则在显示缓冲区中进行显示操作
38. Qt 数据库
-
Qt SQL 模块提供关于数据库编程的支持,它支持多种常见的数据库,如 (大型/网络数据库:MySQL、Oracle、MS SQLServer)、(小型/单机数据库:SQLite、Access)等,Qt SQL 模块包含一系列的类,可以实现数据库的连接、SQL 语句运行、数据获取、数据显示与编辑等操作功能
-
Qt SQL 模块主要类
-
SQLite 数据库简介
- SQLite 是一款开源的、嵌入式关系型数据库
- 它没有独立运行的进程,它与所服务的应用程序在应用程序进程空间内共生共存
- 它的代码与应用程序代码也是在一起的,或者说嵌入其中作为托管它的程序的一部分
- 程序只需要做自己的事,管理自己的数据,不需要详细了解 SQLite 是如何工作的
- 数据库服务器和客户端运行在同一个进程中的好处是:不需要网络配置或管理
- 不用担心防火墙或者地址解析,不用浪费时间管理复杂的授权和权限
- 可以减少网络调用相关的消耗,简化数据库管理,使程序更容易部署
- SQLite 是一款开源的、嵌入式关系型数据库
39. 什么是 QML
40. Qt 单元测试框架
-
QTestLib 是一种针对基于 Qt 编写的程序或库的单元测试工具
- QTestLib 提供了单元测试框架的基本功能,并提供了针对 GUI 测试的扩展功能
- 设计 QTestlib 的目的是简化 Qt 程序或库的单元测试工作
-
QTestLib 的特性
-
创建一个测试的步骤是,首先继承 QObject 类并添加私有的槽,每个私有的槽就是一个测试函数,然后使用 QTest::qExec() 执行测试对象中的所有测试函数