8.1 概述
8.1 概述
本节将简要的介绍Qt中的模型视图框架中的模型-视图-代理框架的基本概念,并以一个简单的使用示例来讲解它们。
8.1.1 基本概念
1.模型(Model)
Qt中的模型-视图架构中的模型有很多,但无一例外这些模型都基于一个叫做QAbstractItemModel类的类,此类又有QProxyModel、QAbstractListModel、QAbstractTableModel、QAbstractProxyModel、QDirModel、QFileSystemModel、QHelpContentModel和QStandardItemModel这些类来继承。其中QAbstractListModel和QAbstractTableModel则是后面我们将会常常用到的列表模型和表格模型的抽象的基类,如果我们要去实现列表或表格,那么我们就需要继承自这两个类来实现我们自己的类。而完成QStringList存储的QStringListModel继承自QAbstractListModel类(也就是说,QStringList内部的存储实际上是通过QStringListModel来实现的存储的,但QStringListModel又是基于QAbstractListModel类),另外我们的数据库中用到的QSqlQueryModel则是基于QAbstractTableModel来实现的(这也很好理解,因为数据库的模型基本上都是以表作为基础的,而数据库中存储的形式都是用的表来存储的)。而QAbstractProxyModel则是以代理模型的抽象类;QDirModel则是以描述文件和目录的存储的模型。后面我们将以一些例子来介绍这些类的基本使用。
QAbstractItemModel
QAbstractListModel
QAbstractTableModel
QAbstractProxyModel
QProxyModel
QStandradItemModel
QDirModel
QFileSystemModel
QSqlQueryModel
...
2.视图(View)
视图是Qt的MVC架构中的另外一种重要的角色,而该框架中的所有的视图都基于QAbstractItemView类,此类会派生出例如QColumnView、QHeaderView、QListView、QTableView、QTreeView等类,而QListView是继承自我们所熟知的QUndoView和QListWidget。而QTableView则是继承自QTableWidget;QTreeView则继承自QTreeWidget。而通过我们前面的学习已经知道,形如QListWidget、QTableWidget、QTreeWidget这些类中实际上已经包含了数据的部分,因此可以理解为是模型和视图集成在一起的类。
QAbstractItemView
QHeaderView
QColumnView
QListView
QTableView
QTreeView
QUndoView
3.代理(Delegate)
同样的,Qt的MVC框架的另一个角色——代理(Delegate)则起到了操作模型中的数据的作用,并且它还能接受来自视图的一些信号,并对其进行响应。而QAbstractItemDelegate类就是所有的MVC架构中的代理类的最基础的抽象类。而QItemDelegate和QStyledItemDelegate就是基于QAbstractItemDelegate类的。而数据库中的QSqlRelationalDelegate又是继承自QItemDelegate的。
QAbstractItemDelegate
QItemDelegate
QStyledItemDelegate
QSqlRelationalDelegate
8.1.2 模型/视图类
MVC框架中提供了一些可以直接使用模型类和视图,常见的模型有QStandradItemModel、QDirModel、QFileSystemModel等。而视图则有QColumnView、QHeaderView、QListView、QTableView和QTreeView等。
案例:使用DirModel并结合QTreeView、QListView、QTableView来实现一个简单的文件浏览器
(1)新建Qt的GUI项目,项目名称就为DirModelEx。不需要创建UI文件
(2) 直接在main.cpp中写上以下的代码
#include "mainwindow.h"
#include <QApplication>
#include <QDirModel>
#include <QListView>
#include <QTreeView>
#include <QTableView>
#include <QSplitter>
#include <QAbstractItemModel>
#include <QAbstractItemView>
#include <QItemSelectionModel>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//1.准备一个Dir的模型
QDirModel model;//创建一个QDirModel对象,为数据访问做准备,这个DirModel还可以设置过滤器,即只有符合条件的文件或目录才能被访问
//2.准备着三个视图
QTreeView treeView;
QListView listView;
QTableView tableView;
//3.将DIR的模型设置到视图上面
treeView.setModel(&model);
listView.setModel(&model);
tableView.setModel(&model);
//4.设置三种视图对应的可选数据的模型
treeView.setSelectionMode(QAbstractItemView::SelectionMode::MultiSelection);//选择方式为多选,其实还有其他的方式来选择,比如单选
listView.setSelectionMode(QAbstractItemView::SelectionMode::MultiSelection);
tableView.setSelectionMode(listView.selectionMode());
/*
* enum SelectionMode {
NoSelection,//不允许选择项目
SingleSelection,//用户只能单选一个项目,且当选择一个项目后,其他的项目都会被取消选择的状态,当用户按下Ctrl并单击已经选择的项目时,该项目会被取消其选择状态
MultiSelection,//支持用户多选多个项目
ExtendedSelection,//当用户以普通的方式选择一个项目时,原先被选中的项目会被取消其选择状态,并且选择到新项目上,若同时按下Ctrl键,那么只对已经当前所正在选择的项目取消其选中状态,其他已选中的项目不受影响。若按下Shift键,则当前正在选择的项目不会改变其选中状态,而会改变其他已经被选中的项目的选中状态。另外这种模式下支持用户拖动鼠标的方式来选择多个项目
ContiguousSelection//当用户选择一个项目时,假设该项目已经被选中,那么将会取消该项目的选择并选择其他项目,若用户在选择了当前项目的同时还按下了Shift键,那么用户当前选中的选项的状态会改变,并且其他被选择的项目也会改变(改变会由原来的状态往新的状态改变)
};
*/
//5.连接这些视图和视图之间的信号和槽的关系
QObject::connect(&treeView,&QTreeView::doubleClicked,&listView,&QListView::setRootIndex);
QObject::connect(&treeView,&QTreeView::doubleClicked,&tableView,&QTableView::setRootIndex);
//6.布局
QSplitter*mainSplitter = new QSplitter;//QSplitter默认就是水平布局的
mainSplitter->addWidget(&treeView);//由于View也是继承自Widget的,所以理所应当可以使用布局器
mainSplitter->addWidget(&listView);
mainSplitter->addWidget(&tableView);
mainSplitter->setWindowTitle(QObject::tr("Model/View Demo"));
mainSplitter->show();
return a.exec();
}
(3)运行后如图所示

本节项目代码:https://files.cnblogs.com/files/blogs/792763/DirModelEx.zip?t=1719138443&download=true

浙公网安备 33010602011771号