阅读了QAbstractItemModel
和QAbstractItemModel
的文档和示例后,我仍然对如何正确实现QModelIndex
的模型感到困惑。
因为我想为existing分层数据结构提供模型,所以我避免使用QModelIndex
或QTreeView
以及与数据复制和同步有关的问题。但是,我无法实现工作项模型(问题太多,发布代码没有用)。
[读取QTreeView
后,似乎很清楚QTreeWidget
QTreeWidget
,但仅依靠模型告诉给定索引的父级。因此,如果不定义至少另一个用于存储这种关系的帮助程序类,似乎不可能为现有数据结构提供抽象树模型。但是,我仍然无法正确实现模型。
假设数据结构就是这个简单的结构:
QStandardItemModel
其中QStandardItemModel
是最顶层的,它类似于一棵树。this answer中显示的树可能如下所示:
QModelIndex
应如何实现QModelIndex
子类以访问现有数据而不进行复制?
这是我的解决方案。
首先,我对does not contain hierarchical information无法存储父子关系的最初猜测是正确的。实际上,方法struct Property {
QString name;
QString value;
};
struct Node {
QString name;
QVector<Property> properties;
};
struct Track {
int length;
QString channel;
};
struct Model {
QVector<Node> nodes;
QVector<Track> tracks;
};
只是调用Model
,而实现父方法的任务留给了模型类。当基础模型是适当的树时,指向树节点的指针可以存储在QTreeView
类中,但是在我的情况下,我们正在处理“虚拟”树,并且这种关系不可用。因此,我们被迫引入某种额外的存储空间,以便能够分辨出我们在树中的位置。如果QTreeView
本机支持具有指向父索引的指针,则可以更轻松地解决此问题。但是由于Model
├─Nodes
│ ├─Node "node1"
│ │ └─Properties
│ │ ├─Property property1 = value1
│ │ └─Property property2 = value2
│ └─Node "node2"
│ └─Properties
│ └─Property property1 = someValue
└─Tracks
├─Track 1, ...
├─Track 2, ...
└─Track 3, ...
是一个值类,所以我们不能为父类添加pointer,而是必须将所有父级索引存储在QAbstractItemModel
类中,也许Qt开发人员有一些不错的方法这样做。因此,我在QAbstractItemModel
的内部指针字段中存储了QModelIndex
。有一些需要注意的事情,例如避免分配过多的此类索引,还记得在不再需要这些索引时记住释放内存(我们在这里不能使用QObject层次结构)。当模型是读写模型时,可能还要解决其他问题,但是在这种情况下,我正在处理只读模型。
我的实现如下。方法QModelIndex::parent
和QAbstractItemModel::parent
定义此特定的虚拟树。其他方法可以抽象到可以重用的类中。
QModelIndex
实现:
QModelIndex