使用beginResetModel刷新模型时如何保留TreeView选中状态?
解决QSortFilterProxyModel重置模型后保留选中状态的方案
1. 保存选中项的唯一标识(而非代理索引)
不要直接保存QSortFilterProxyModel的索引——重置模型后这些索引会完全失效。转而保存源模型(QAbstractItemModel)中项的可靠唯一标识,常见方案有三种:
- 项自带的业务ID字段(如果模型数据中包含)
- 源模型的持久化索引(
QPersistentModelIndex),需先把代理索引转换为源模型索引再创建 - 项的层级路径(比如从根节点到当前项的文本/ID序列)
示例代码(用持久化索引保存):
// 重置模型前保存选中状态 QList<QPersistentModelIndex> selectedSourceIndexes; const auto selectedProxyIndexes = treeView->selectionModel()->selectedIndexes(); for (const auto& proxyIdx : selectedProxyIndexes) { if (proxyIdx.isValid()) { auto sourceIdx = proxyModel->mapToSource(proxyIdx); selectedSourceIndexes.append(QPersistentModelIndex(sourceIdx)); } }
2. 执行模型重置操作
正常调用beginResetModel()和endResetModel()完成源模型的数据更新:
sourceModel->beginResetModel(); // 此处执行你的数据刷新逻辑 sourceModel->endResetModel();
3. 重置后恢复选中状态
将保存的源模型标识转换回代理模型的有效索引,再恢复选中状态:
// 恢复选中状态 QItemSelection selection; for (const auto& persistentSourceIdx : selectedSourceIndexes) { if (persistentSourceIdx.isValid()) { auto proxyIdx = proxyModel->mapFromSource(persistentSourceIdx); if (proxyIdx.isValid()) { selection.select(proxyIdx, proxyIdx); } } } treeView->selectionModel()->select(selection, QItemSelectionModel::ClearAndSelect);
额外注意事项
- 如果用ID或路径作为标识,需要在源模型中实现对应查找方法,根据标识定位到源模型索引后再转换为代理索引。
- 确保源模型更新后,目标项仍然存在(若项已被删除,自然无法恢复选中)。
- 若树结构有新增/删除父节点的变化,路径标识可能失效,优先使用持久化索引或业务唯一ID。
内容的提问来源于stack exchange,提问作者Antriksh kakkar
相关产品推荐
相关产品推荐

