MySQL on Qt (3): SQL的MVC结构基础知识总结
写在前面:
大一下学期的 CPP 大作业“自主订餐系统”可真是颇费了一些力气,每天晚睡早起撸代码,课都没听,很多知识都是现学现用。
为了避免当时学到的东西给全部忘光光(`_>`,我这脑子啊。。。),所以我把当时大作业的一些核心部分(一些零碎的小细节,能记就记)给记录一下,一方面是复习,一方面也方便以后用到的时候查阅。
这篇文章是大作业 MySQL + SQLite 操作相关部分的第三章,主要讲一下 Qt 中 SQL 的 MVC 结构的基础知识,包括一部分的 MVC 原理介绍和基础使用。
什么是 MVC 结构
关于 MVC 结构的具体介绍,可以看一个名为《Qt中文文档》的 Github 项目中 Qt 关于 MVC 的官方文档的中文翻译版(这里打个广告=。=):
模型/视图 编程
https://www.cryfeifei.cn/2020/08/08/qt-zhong-wen-wen-dang-mo-xing-shi-tu-jian-jie/
也可以看上一篇我转载自网络的文章:
Qt Model/View(模型/视图)结构(无师自通)
以上两篇网络文章我都转载到了我的博客中。
这里我就不再讲太多太细的知识和原理,只是简单概括一下。
GUI 应用程序的一个很重要的功能是由用户在界面上编辑和修改数据,典型的如数据库应用程序。数据库应用程序中,用户在界面上执行各种操作,实际上是修改了界面组件所关联的数据库内的数据。
Model/View(模型/视图)结构是 Qt 中用界面组件显示与编辑数据的一种结构,视图(View)是显示和编辑数据的界面组件,模型(Model)是视图与原始数据之间的接口。
将界面组件与所编辑的数据分离开来,又通过数据源的方式连接起来,是处理界面与数据的一种较好的方式。Qt 使用 Model/View 结构来处理这种关系,Model/View 的基本结构如图 1 所示。
其中各部分的功能如下:
- 数据(Data)是实际的数据,如数据库的一个数据表或SQL查询结果,内存中的一个 StringList,或磁盘文件结构等。
- 视图或视图组件(View)是屏幕上的界面组件,视图从数据模型获得每个数据项的模型索引(model index),通过模型索引获取数据,然后为界面组件提供显示数据。Qt 提供一些现成的数据视图组件,如 QListView、QTreeView 和 QTableView 等。
- 模型或数据模型(Model)与实际数据通信,并为视图组件提供数据接口。它从原始数据提取需要的内容,用于视图组件进行显示和编辑。Qt 中有一些预定义的数据模型,如 QStringListModel 可作为 StringList 的数据模型,QSqlTableModel 可以作为数据库中一个数据表的数据模型。
开启 MVC 之旅
讲完又臭又长的理论,我们就要进入令人激动的实践啦。
外甥打灯笼,这次我也是写了一个 Demo 来演示具体的应用。
与以往不同,这次会先把全部工程代码贴出来再分块讲。
sqlmvcdemo.h
:
1 |
|
sqlmvcdemo.cpp
:
1 |
|
Model/View 相关的类
demo 头文件sqlmvcdemo.h
比较重要的部分是头文件include
部分,这涉及了 Qt 中 MVC 相关的类。
Qt 中 MVC 结构相关类列表如下:
从图里列出的类名基本上就能推测出我们要用到哪些类:
1 |
其中 QHeaderView
类比较特殊,看起来与我们要使用的 SQL 毫不相关对不对。但其实它作用很大,到后面用到的时候再来说一说。
SQL Model/View 绑定
正如前面所说,Model 作为数据模型为操作数据提供了相关接口,因而在使相关 Model 时我们要绑定到具体的数据上。在我们这次使用的 SQL MVC 模型中,就是要把 QSqlTableModel
与 QSqlDatabase
对象绑定。所以便有了如下实例化代码:
1 | _tableModel = new QSqlTableModel(nullptr,_db); // Construct from allocated Database |
这样待绑定的数据库连接后,QSqlTableModel
对象就可以对数据库进行相关操作了。
这里要注意一下QSqlTableModel
模型指定一个表后,还要执行一下QSqlTableModel::select()
函数才能选中表中的数据。
1 | //Model |
关于数据模型我们还要考虑一个小细节:用户提交策略
一般情况下,用户完成数据编辑后,会有两种提交策略:
- 自动提交(默认),即编辑完数据( dataChanged() )后,数据模型自动提交。
- 手动提交,即编辑完数据后,需手动调用提交函数方能提交用户数据修改。
若要设置为手动模式,我们需要对 Model 进行如下设置:
1 | _tableModel->setEditStrategy(QSqlTableModel::OnManualSubmit); // Manual submit |
并在相应位置手动调用该函数提交:
1 | _tableModel->submitAll() |
前面也说过,View 是视图结构,与数据模型绑定,为用户操作提供相应的接口,并将用户操作具体应用到数据模型,数据模型再将操作实际应用到数据中。在我们这次使用的 SQL MVC 模型中,就是要把 QTableView
与 QSqlTableModel
绑定。所以便有以下代码:
1 | _tableView->setModel(_tableModel); |
对 View 控件的设置,主要包括以下方面:
- 表头设置
- 编辑策略
- 代理
View 表头设置
先来讲一下 View 控件表头的设置。
还记得前面提到的QHeaderView
类嘛?这里对表头的各种设置,就必须引用该类。
首先是设置表头,这里以水平表头为例:
1 | // Init Hearders |
然后我们肯定会遇到要设置某一列宽度的情况:
1 | // Set width of cols |
当然,我们还能设置某一列的宽度随着界面缩放比例而改变(建议开启该选项,这样才能让表格占满 View 控件,美观度++):
1 | // Resize with stretch |
再来设置一下让数据按行交替现实不同的颜色:
1 | // Color varies in rows |
编辑策略
按行选中而不是按单元格选中:
1 | _tableView->setSelectionBehavior(QAbstractItemView::SelectRows); // SelectRows |
单选:
1 | _tableView->setSelectionMode(QAbstractItemView::SingleSelection); // SingleSelection |
只读:
1 | _tableView->setEditTriggers(QAbstractItemView::NoEditTriggers); // NoEditTriggers |
代理
例如本 Demo 中的 Gender 项,我想编辑的时候出现一个“男生|女生”的下拉框而不是仅仅出现一个0或1的编辑框,这个时候我们就需要使用代理。
代理这里先卖一个关子。
好吧其实不是卖关子,而是太长了实在是不想在这一章讲了。。。
代理是一个很庞大的部分,我打算在下一章讲一些皮毛的东西。
到这里本章的内容基本上就结束了,下一章我会讲一下代理最为皮毛的一些原理和应用。
Qt Model/View(模型/视图)结构(无师自通)