了解 Qt 视图模型架构:何时创建以及如何清理 QAbstractItemModel 实现中的索引?

2023-12-10

我目前正在将我的项目从QTreeWidget to QtreeView,并且有很多由于对Qt模型视图设计理解不佳而导致的问题。到目前为止,即使在 Qt 示例中我也找不到答案。

我已经实现了我的QAbstractItemModel。我正在返回要在中查看的字符串QTreeView通过data方法。现在,底层数据将在运行时发生变化。为了处理这个问题,我的模型订阅了一个通知emit dataChanged(index(0,0), index(rowCount() - 1, LastColumn));。问题是:如何创建和清理QModelIndex物体? Qt 示例之一重新实现index方法,所以我做了同样的事情:

QModelIndex CFileListModel::index(int row, int column, const QModelIndex &/*parent*/) const
{
    QModelIndex index = createIndex(row, column);
    return index;
}

然而,在该示例中,数据是静态的,而在我的例子中,它会在运行时发生变化。是我的index实施正确吗?如果什么index对于同一坐标被多次调用?我是否需要在发出之前以某种方式清理旧索引dataChanged?


根据 C++ 的语义,您关于“删除”索引的问题没有任何意义。您根本无法销毁从函数内部按值返回的对象 - 至少在不诉诸有目的的肮脏黑客的情况下是这样。所以让我们忘记它吧。

The dataChanged信号和索引的生命周期并没有真正相关。当你的index()方法返回一个索引,你不是可以“删除”它的人;无论谁给你的模特打电话index()方法负责破坏索引。没关系,您给出的索引无论如何都不会分配在空闲存储中,因此删除的概念根本不适用。

The QModelIndex盒子上写着:索引。当谈到如何使用它时,它非常像 C++ 迭代器。它带有一些与迭代器警告相同的警告:

  1. 它必须由模型使用工厂方法创建index()。在内部你使用createIndex()工厂在模型中为您创建它。想想 C++ 容器的迭代器返回方法(begin(), end(), etc.).

  2. 必须立即使用,然后丢弃。如果您对模型进行更改,它将不再有效。同样的一般限制也适用于 C++ 容器迭代器。

  3. 如果您需要随着时间的推移保留模型索引,请使用QPersistentModelIndex。 C++ 标准库不提供此功能。

索引的生命周期是您无法控制的。你创建它,你把它分发出去,并期望它会根据这个协议被使用。用户(例如视图)在使用它时应遵守上面列出的限制。例如,如果一个视图保留索引的时间太长(通过干预修改),那么它会导致未定义的行为(例如崩溃),这是完全可以接受的。

当您发出(或接收,如果您是视图或代理模型)时dataChanged,您不应期望在此之前给出的任何索引仍然可用。当然,持久索引应该仍然有效,但是如果删除了指向的索引(想象一下从电子表格中删除了一个单元格,not单元格的数据被更改!)。

如果您给出了索引,则发出dataChanged, and any当你的模型的方法被旧的索引调用时,你可以自由地崩溃、断言、中止等等。

我们还要明确一下您如何使用dataChanged:只要给定索引处的数据项发生变化,您就应该发出它。您应该尽可能具体:它是not如果事实上一切都没有改变,那么简单地告诉你的观点一切都改变了,这是一个好主意。如果一个索引发生了变化,则发出信号topLeft and bottomRight设置为相同的索引。如果一个小矩形区域发生了变化,则发出该矩形的角点。如果多个不相关的项目发生了更改,并且距离太远而无法有意义地捆绑在一个小的封闭索引矩形中,则应该为每个更改的项目单独指示此类更改。

你绝对应该使用模型测试验证您的模型行为是否正常。

这可以通过添加modeltest.cpp and modeltest.h到您的项目,并为每个模型实例实例化测试器。您可以直接在模型中执行此操作:

#include "modeltest.h"

MyModel(QObject * parent) : ... {
   new ModelTest(this, parent);
   ...
}

您还需要处理模型的持久索引,这是一个单独的问题。文档说:

为可调整大小的数据结构提供接口的模型可以提供 insertRows()、removeRows()、insertColumns() 和 removeColumns() 的实现。实现这些功能时,重要的是在模型尺寸发生变化之前和之后通知任何连接的视图:

  • insertRows() 实现必须在将新行插入数据结构之前调用 beginInsertRows(),并在之后立即调用 endInsertRows()。
  • insertColumns() 实现必须在将新列插入数据结构之前调用 beginInsertColumns(),并在之后立即调用 endInsertColumns()。
  • 从数据结构中删除行之前,removeRows() 实现必须调用 beginRemoveRows(),并在之后立即调用 endRemoveRows()。
  • 从数据结构中删除列之前,removeColumns() 实现必须调用 beginRemoveColumns(),并在之后立即调用 endRemoveColumns()。

这些函数发出的私有信号使附加组件有机会在任何数据变得不可用之前采取行动。使用这些开始和结束函数封装插入和删除操作还使模型能够正确管理持久模型索引。如果您希望正确处理选择,则必须确保调用这些函数。如果插入或删除带有子项的项目,则无需为子项调用这些函数。换句话说,父项将照顾其子项。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

了解 Qt 视图模型架构:何时创建以及如何清理 QAbstractItemModel 实现中的索引? 的相关文章

随机推荐

  • 在渲染 JS canvas 之前加载图像

    我正在编写一个简单的游戏来学习 JS 并且在此过程中我正在学习 HTML5 所以我需要在画布上绘制东西 这是代码 let paddle new Paddle GAME WIDTH GAME HEIGHT new InputHandler p
  • 应用程序窗口预计在应用程序启动结束时有一个根视图控制器

    当我的应用程序启动时出现上述错误 以下代码来自我的 AppDelegate h 文件 import
  • 如何导入数据文件进行UFT API测试?

    我正在开发一个项目 需要在运行时动态导入测试数据并运行与测试数据对应的API测试 我尝试使用 XMLload 直接从 xml 请求加载 这似乎运作良好 但就像 GUI 测试一样 我们导入测试数据 我希望 API 测试也一样 我可以动态地从外
  • SVG - 从中​​心重复缩放路径(脉动)

    我有一个中心点为 100 100 的 svg 图形
  • 从类或实例设置属性时的查找过程是什么?

    Python 简而言之描述了从类获取属性时的查找过程 例如cls name以及从实例获取属性时的查找过程 例如obj name 但我不确定何时设置属性 设置属性 请注意 属性查找步骤仅按照刚刚描述的方式发生 当您引用属性时 而不是当您绑定属
  • 使用vtd-xml解析xml文件

    如何在 java 或 C 中使用 vtd xml 解析如下所示的 xml 文件
  • IE11 预览版中未定义“WebForm_DoPostBackWithOptions”

    IE11来了 我刚刚安装了开发者预览版 但是 如果我运行一些 Web 应用程序并收到错误WebForm DoPostBackWithOptions未定义 当我玩自动回发时弹出错误DropDownList 而且之前IE10好像也有类似的问题
  • Postgres 自然排序依据

    我在 postgres 中的一列中遇到了排序问题 其中包含诸如版本之类的值 版本因字符而异 其值如下 无序 1 2 1 3 1 10 1 1 9 我如何按自然顺序排序 以便当我发布时SELECT version FROM TABLE A O
  • Oracle 10g 中的聚合字符串连接[重复]

    这个问题在这里已经有答案了 我看到上一个问题 其中表格包含 否 和 名称 列 以及其他与数字列分组的问题 但无法实现为我的案例提供的答案 我需要做同样的事情 但是使用非数字分组 源表是 tbl1 包含以下列 POD Name North R
  • iOS 7.0 未找到代码签名身份

    证书有效 xcode 5 iOS 7 代码签名错误 未找到代码签名身份 没有代码签名 匹配的身份 即证书和私钥对 在构建设置中指定的配置文件 iOS Team 找到配置文件 CodeSign 错误 代码签名是 SDK iOS 7 0 中的产
  • 在没有 stdarg 的情况下访问可变参数函数参数

    有没有办法使用指针访问函数中的可变参数 我尝试做类似的事情 void test int p int firstarg p 1 但这行不通 va start 和 va arg 如何访问这些参数 没有portable这样做的方法 并且没有充分的
  • Selenium:获取 chrome 时未正确关闭

    当我在 selenium 框架中重新打开 chrome 浏览器时 收到 chrome 未正确关闭的错误消息 在框架中 我使用以下代码在每个测试用例的开头打开浏览器实例 if browserType equalsIgnoreCase Chro
  • 为什么 git 认为整个文件已更改,而仅更改了其中的一部分

    我面临着一个奇怪的情况git 我刚刚编辑了一个长文件中的几行 但是当我去提交更改时 我看到 git 只是用红色突出显示了整个文件内容 怎么了 我正在使用 git 的 Windows GUI 编辑 我现在记得的一件事是我在上次提交中将 csp
  • Dart 空检查习惯用法或最佳实践是什么?

    我有以下形式的赋值和空检查 以避免在我的地图中进行双重查找 在 Dart 中是否有更好或更惯用的方法来做到这一点 bool isConnected a b List list return list outgoing a null list
  • 如何实现规则引擎?

    我有一个存储以下内容的数据库表 RuleID objectProperty ComparisonOperator TargetValue 1 age greater than 15 2 username equal some name 3
  • 如何在Python中没有文本的情况下通过文本单击链接

    我正在尝试从 vivino com 抓取 Wine 数据 并使用 selenium 使其自动化并抓取尽可能多的数据 我的代码如下所示 import time from selenium import webdriver browser we
  • RestSharp简单完整示例[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 我一直在尝试创建一个简单的原型 Web 应用程序 使用 RestSharp 调用 Rest API 我一直找不到一个很好的例子 有人可以分享并指导我
  • TYPO3 在每个页面插入插件

    我有 TYPO3 版本 7 6 18 我想在每个页面中插入一些插件 我想这可能与打字稿有关 请帮帮我 该怎么办 如果您想在每个页面上插入特定的插件 您只需将其添加到您的页面中 如下所示 page PAGE page 10 FLUIDTEMP
  • 在 XCode 7.1.1 中运行 UI 测试时 iOS 应用程序失败

    我正在为我的 iOS 应用程序创建第一个 UI 测试 每次运行测试时我都会收到错误 UI Testing Failure App accessibility isn t loaded 请参阅附图 加上调试控制台中的错误消息 dyld Lib
  • 了解 Qt 视图模型架构:何时创建以及如何清理 QAbstractItemModel 实现中的索引?

    我目前正在将我的项目从QTreeWidget to QtreeView 并且有很多由于对Qt模型视图设计理解不佳而导致的问题 到目前为止 即使在 Qt 示例中我也找不到答案 我已经实现了我的QAbstractItemModel 我正在返回要