我有自己的 View ,直接基于 QAbstractItemView
。
一般来说,我需要存储一些关于特定模型项目的信息。
所以在我看来,我有一个从 QModelIndex
到描述部分项目的结构的映射。
然后我主要在 View 的 paintEvent
上使用这些数据。
问题是,QModelIndex 不是持久的,它可能会过时。
因此,当从模型中插入或删除行时,一些 QModelIndex
可能会变得无效,我不应该依赖它们。
那么我如何在模型中的项目和我在 View 中使用的一些装饰数据之间建立关系?
QPersistentModelIndex
似乎是处理这些事情的合适工具,但我知道它的性能(我的模型和 View 可能很大)。
QPersistentModelIndex
的另一个问题是它可能不应该用作 map 的键(在我的例子中就是这样),因为它可能(并且将会)改变并使 map 不一致。
我查看了 Qt 的 QTreeView 和 QListView 实现,了解它们如何处理行删除/插入,但它们似乎只是删除了所有数据。
所以在这一点上我看不出有什么简单的方法可以解决我的问题。
最佳答案
您可以安全地使用 QPersistentModelIndex
作为 map 或 哈希键。
即使底层 QModelIndex 发生变化,“持久”部分也会确保所有 QPersistentModelIndex
在保留其身份的同时保持最新,即 operator ==
和 qHash()
返回一致的值。
也就是说,您不应该在 View 中存储有关索引的数据。数据应该由模型存储。
这似乎是它在 Qt 类中的完成方式: View 正在对 QAbstractItemModel::data()
进行大量调用。 .
我认为唯一值得存储在 View 中的数据是“缓存数据”,即:
- 不是由模型直接提供的
- 需要根据模型数据进行大量计算
- 特定于 View
如果这 3 个条件中的任何一个不满足,我个人的偏好是将数据存储在模型中。
编辑
与我最初的回答相反,您不能安全地使用 QPersistentModelIndex
作为QMap
键。
原因是QMap
使用 operator <
用于插入和查找数据。
这里的问题是 bool QPersistentModelIndex::operator<(const QPersistentModelIndex &other) const
只是 bool QModelIndex::operator<(const QModelIndex &other) const
的代理它按行和列比较索引。
这意味着 QPersistentModelIndex
的排序顺序不持久,当索引在模型中移动时会发生变化。
然而,QMap
不知道排序顺序已更改。此时在 QMap<QPersistentModelIndex, T>
中搜索一个值就像在未排序的数组上进行二进制搜索一样糟糕。
请注意,此问题不仅限于 QMap
,它会影响所有基于键顺序的容器,如 std::map
.但是,不依赖于排序的容器( QHash
、 std::unordered_map
……)不受影响。
关于c++ - 存储有关 View 中项目的持久信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27587922/