欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于 QAbstractItemModel 学习的一点分享

程序员文章站 2024-03-17 17:41:16
...

关于 QAbstractItemModel 学习的一点分享

简介:

Qt的模型、视图框架对处理一些复杂数据结构的可视化非常有用。

Qt提供了三种常用的数据模型:QAbstractListModel (表单模型)、QAbstractTableModel (表格模型)、QAbstractItemModel (项目模型)。
其中第三种模型最灵活。前两种模型都是继承第三种模型的类的。

Qt的帮助文档里有提到:

If you need a model to use with an item view such as QML’s List View element or the C++ widgets QListView or QTableView, you should consider subclassing QAbstractListModel or QAbstractTableModel instead of this class.

可以看出,如果是listView 或者 tableView 那么就考虑前两种数据模型,但是如果是treeView,那就只好选择QAbstractItemModel (项目模型)了。

可以这样理解,QAbstractListModel 是QAbstractTableModel 的特殊化,QAbstractTableModel 是QAbstractItemModel 的特殊化。

接下来,我们着中来理解下QAbstractItemModel类。

关于QAbstractItemModel类的细节描述:

1、QAbstractItemModel 类提供了共模型视图框架中的其他组件访问的接口。

2、使用QAbstractItemModel 类,应当子类化。不能直接创建该类的对象。

3、AbstractItemModel 类 支持的 The underlying data model (底层的数据模型)是一个类似hierarchy of tables(有层级关系的表格),如果没有层级,那就只有rows(行) 和colums(列)。但在AbstractItemModel 类中,还有QModelIndex(索引),这样,每一个Item 就是一个独立的表格单元。如下图:

关于 QAbstractItemModel 学习的一点分享
4、对于每一个数据单元(item of data)可以通过index() 索引,它的子项可以通过sibling()索引,它的父项可以通过parent()索引。

5、对于每一个数据单元都有一些data elements(数据元素)来界定( Qt::ItemDataRole)数据的角色。该数据元素可以通过data()放来来获取:

如:
QVariant str = item2->data(Qt::ToolTipRole);

qDebug()<<str;

下表列出了数据角色:

关于 QAbstractItemModel 学习的一点分享
什么是数据角色?可以这样理解对于每个item呈现给用户的视角是多方面的,比如:ToolTipRole 角色中的数据是只有当鼠标移到视图中多对应的Item才会显示。
例如,下图中选中的Item中 有三个角色,分别是蓝色的图标、字符"B"、提示“”indexB“”。
关于 QAbstractItemModel 学习的一点分享
6、在每一个item中,每个数据角色会对应一个数据,通过setData()方法来为指定的数据角色设定数据。setItemData()方法 则是为所有的数据角色设定相同的数据。

7、hasChildren()方法可以确认是否有子项。

8、对于一个层级的表格,都有关于行和列的操作
rowCount() 、columnCount()、 insertRows(), insertColumns(), removeRows(), and removeColumns().

9 、该模型该提供了一些信号来表示数据的变化:dataChanged()、headerDataChanged() 、layoutChanged()

子类化该模型

1、在只读模型和基本的可编辑模型中,至少需要重写index(), parent(), rowCount(), columnCount(), data()这些函数。

2、重写 hasChildren()函数来提供一些特殊的模型的行为。

3、如果模型是可编辑的,那么还需要重载setData() 和 flags().

4、重写headerData()和setHeaderData()对标题进行编辑。

5、在setData()和setHeaderData()函数中必须明确的加载 dataChanged() and headerDataChanged() 信号。

6、对于自定义模型,需要创建模型的索引,这里会用到createIndex()。

7、模型的重构会用到插入删除行列insertRows(), removeRows(), insertColumns(),and removeColumns(). 在这些操作中it is important to notify any connected views about changes to the model’s dimensions both before and after they occur:

例如:

bool TreeModel::insertColumns(int position, int columns, const QModelIndex &parent)
{
    beginInsertColumns(parent, position, position + columns - 1);
    const bool success = rootItem->insertColumns(position, columns);
    endInsertColumns();

    return success;
}

8、重写fetchMore() and canFetchMore()使数据模型递增。

有关子类化的相关实现 可以参考Qt的示例代码:Simple Tree Model

在Qt的帮助文档中还有一篇 Model/View Programming 的介绍,该文档中Model Subclassing Reference 就有提到如何子类化。