0. 前言
上一篇文章讲了Qt中Model/View
框架的起源(和给人的优越感 ),以及它大概是怎么个思路,最后花了不少篇幅讲了为什么要使用Model/View,现在想想多是在给自己打气,好坚持学下去👻。
本文开始介绍有关函数接口了,既然数据Data
是用户自定义的,那就从Model
开始介绍。
系列文章回顾:
Qt Model/View 学习(1) - 是什么和为什么?
1. Model有关类
先上一张Qt有关Model
类的UML类图,空心箭头表示泛化关系,也就是派生类指向基类。如果想了解更多一点关于UML类图的知识,可以移步这篇文章。
图中C位自然是QAbstractItemModel
了,它继承自QObject
获得了信号和槽机制,派生出了诸多Model
类,但其中核心就2个:
QAbstractListModel
:提供一维矩阵模型的抽象基类;既然是抽象类,那我们只能派生自己的类才能使用;QAbstractTableModel
:提供表格模型的抽象基类;
其它的有:
QFileSystemModel
:提供本地文件系统的数据模型,使用场景十分受限,也可以先不用过多理会;QAbstractProxyModel
:提供排序、过滤、或其它数据处理任务的代理模型,暂时可以不用过多理会;QStandardItemModel
:提供了一种使用控件的Model
类,换言之,它Model了,但没有完全Model,在学习Model/View
的路上可以不用过多理会;QDirModel
:官方建议使用性能更好的QFileSystemModel
,那可以不用过多理会;
所以,虽然继承树似乎内容庞大,但我们只要搞懂QAbstractListModel
和QAbstractTableModel
这俩,就能掌握Model的精髓了,好耶!
而这俩,从名字看就很简单:一个一维数组一个二维数组,而且打开这两个类的文档,篇幅极少,滚动条那么大一个,就这?
2. Model索引:QModelIndex
先别着急膨胀,QAbstractListModel
和QAbstractTableModel
的文档内容少是因为大部分内容都在QAbstractItemModel中实现了,而打开QAbstractItemModel
类的文档就又有些劝退了……
不过换言之,只要掌握了QAbstractItemModel
,就能掌握Model
的精髓了。
后续将用 “
Model
类” 来指代从QAbstractItemModel
派生的类;
在上一篇文章中讲过,Model
是对数据的解析模型,比如20个散装变量,可以被解析成一个4*5
的矩阵。而如何去索引矩阵中的数据就是重点了,这需要介绍本小节的主角QModelIndex
了,先上一张图:
以下是核心解释,看完这里基本就掌握索引了:
-
QModelIndex
是Model
类的索引,基本特征是二维索引,通过row()
和column()
方法获取其位置; -
但它不是纯二维索引,还提供了
parent()
和child()
方法获取上层节点和下层节点。还提供了sibling()
方法,提供row
和column
的偏移量来获取同一层的兄弟节点; -
一般使用
Model
类的createIndex()
方法创建索引,需要提供row
,column
和parent
; -
使用构造函数创建的
QModelIndex
对象是无效的,无效索引通常被用于指代最顶层对象的parent
节点,可通过isValid()
方法来判断是否有效,有效表示该对象是某个Model
对象的有效索引; -
要获取一个
Model
类的索引时,使用index()
方法获取,但很遗憾该接口一般不是公开的;如果设为公开,或许会比较破坏封装性;
-
QModelIndex
对象最好是随用随取,不要指望某个QModelIndex
在调用了其它Model
函数之后还能起作用,这里暗示QModelIndex
是“对位不对人”的,如果希望“对人不对位”,可以使用QPersistentModelIndex
类;但尽管使用
QPersistentModelIndex
类也最好先用isValid()
断一下,因为有可能索引的对象人没了。
最后再补一嘴,为什么Model类的索引被设计成这样?
简单来说,为了适应常见的数据结构:树结构 和 矩阵结构。QModelIndex
的行和列索引使其能够支持矩阵结构,parent()
和child()
接口使其能够支持树结构。
下图是官方用来说明三种常用模型(列表、表格、树)的图。放到这里来参考的原因是QModelIndex的表示能力是大于以下三种模型的,因为每个QModelIndex
对象都可以作为parent
,对于每个parent
,都可以索引其二维孩子child
。
搞清楚如何索引之后,Model类基本就 攻略了30% 了,是不是很简单呢?
3. 小结
Model
类主要搞懂QAbstractItemModel
即可,搞明白之后由该类派生的QAbstractListModel
和QAbstractTableModel
也会很容易理解;Model
类主要是完成原始数据到模型的映射,所以如何索引模型数据是关键,Qt中采用QModelIndex
类来索引模型数据;QModelIndex
类提供了行、列、父、子、兄弟的接口,以此实现对常见的矩阵结构和树结构原始数据的支持。
如有错误欢迎指正,共同进步~
今天你学废了吗?