如何在 QAbstractItemModel 中为 QTreeView 创建人工节点

Posted

技术标签:

【中文标题】如何在 QAbstractItemModel 中为 QTreeView 创建人工节点【英文标题】:How to create artificial nodes in QAbstractItemModel for QTreeView 【发布时间】:2010-02-01 10:42:19 【问题描述】:

我的问题是关于 Qt 及其 QAbstractItemModel。

我有一个字符串和双精度的映射 (std::map<stringclass, double>),我想在 Qt 小部件中呈现它。虽然我可以为此使用QTableView,但我想利用地图的键是“abc.def.ghi”形式的事实,其中可以有多个以“abc.def”开头的字符串,甚至更多以“abc”开头。

所以我想设置一个树数据模型来以QTreeView 之类的形式呈现项目

(-) abc
    |--(-)def      
          |--ghi    3.1415
          |--jkl    42.0815
    |--(+)pqr
    |--(+)xyz

我的std::map 的键是树的叶子,所有其他节点都是临时和辅助构造,以支持折叠以方便用户使用。

不幸的是,rowCountindexcolumnCountdata 方法具有 const 修饰符,所以我不能简单地为我的 QAbstractItemModel 中的标题设置辅助数据结构派生并更改该数据结构。

最好的做法是什么?我应该在std::map 和QAbstractItemModel 之间设置另一个类层还是有更聪明的方法来做到这一点?


编辑 1:std::map 可以在显示和使用 QTreeView 时更改,因此辅助节点可能会被丢弃并重建。我的假设是处理这个问题的最好方法是重组QAbstractItemModel - 或者我应该简单地丢弃那个模型并将一个新构建的模型分配给QTreeView?在这种情况下,我想我可以在构造函数中设置所有节点,而不会被方法的 const 性所困扰。

【问题讨论】:

【参考方案1】:

我会解析地图并基于它创建一个树数据结构。确保在更改地图时同步模型。 如果此同步步骤过于复杂,您可能希望从一开始就将数据保存在树结构中,并在必要时转换为地图。

在模型函数中动态解析地图对我来说似乎是个坏主意,您希望这些函数尽可能快。

【讨论】:

【参考方案2】:

我不明白 const 修饰符会成为一个真正的问题。

rowCountindexcolumnCountdata 方法被调用时,您想修改QAbstractItemModel 派生的哪些成员?您可以很好地存储对地图的引用,并从中计算所有内容。无需修改地图本身来提取所需的信息(据我所知!)。

在 EDIT1 和 cmets 之后编辑 : 如果您的地图一定会被修改,请将其用作您自己类中的基础结构。 如果由于模型的生命周期可能超过地图的生命周期而无法保留对地图的引用,请使用智能指针确保不会发生这种情况。

【讨论】:

你说得对,我不需要也想更改std::map,但是如果我将QAbstractItemModel 子类化以添加私有成员(例如,用于缓存辅助节点),我无法修改这些方法中的私有成员。 std::map 可能是 QTreeView 的生命周期,因此可能需要在不重新构建模型的情况下重新构建模型。 我明白了。但是,如果您想重构模型,请在没有 const 问题的情况下使用 std::map 对其进行初始化!

以上是关于如何在 QAbstractItemModel 中为 QTreeView 创建人工节点的主要内容,如果未能解决你的问题,请参考以下文章

如何使用带有 Qabstractitemmodel 的 QSortFilterProxyModel 隐藏第一列

如何使用 QAbstractItemModel 从 QTreeView 中删除行?

QAbstractItemModel data() 永远不会被调用

以编程方式检查QAbstractItemModel / QTreeView中的项目

QAbstractItemModel - QModelIndex 对象在创建时是不是应该被缓存?

QAbstractItemModel::columnCount - 每行的可变列数