如何解决QSortFilterProxyModel传入错误模型索引的异常?
解决QTreeView切换匹配节点时的QSortFilterProxyModel索引异常问题
问题场景
在绑定了QSortFilterProxyModel的QTreeView控件中,点击「Next」按钮执行切换至下一个匹配节点逻辑时,触发异常:QSortFilterProxyModel: index from wrong model passed to mapToSource。
异常原因
核心问题是索引所属模型不匹配:
- 查找逻辑(
findNext、_findNext)直接操作的是源模型(mModel)的索引; - QTreeView的选择模型(selectionModel)绑定的是代理模型(QSortFilterProxyModel)的索引空间;
- 直接将源模型索引传给TreeView的选择模型,会因为模型上下文不匹配抛出异常。
解决方案
所有与TreeView交互的索引必须是代理模型的索引,源模型索引需先完成模型间的映射:
- 从TreeView获取选中索引时,先映射为源模型索引,用于查找逻辑;
- 查找得到源模型的匹配索引后,再映射为代理模型索引,传给TreeView执行选择、滚动等操作。
修改代码示例
首先确保类中持有代理模型的指针(比如新增QSortFilterProxyModel* mProxyModel成员变量),初始化时完成绑定:
// 初始化代码示例 mProxyModel = new QSortFilterProxyModel(this); mProxyModel->setSourceModel(mModel); mTreeView->setModel(mProxyModel);
然后修改findNext()函数:
void RegistryTreeView::findNext() { QModelIndex sourceFromIdx; QModelIndexList selectedIndexes = mTreeView->selectionModel()->selectedIndexes(); if(selectedIndexes.isEmpty()) { // 从源模型获取根节点索引 sourceFromIdx = mModel->index(0, 0); } else { // 将选中的代理模型索引映射为源模型索引 QModelIndex proxySelectedIdx = selectedIndexes.first(); sourceFromIdx = mProxyModel->mapToSource(proxySelectedIdx); } // 查找得到源模型的匹配索引 QModelIndex sourceNextIdx = findNext(mSearchEdit->text(), sourceFromIdx); if(!sourceNextIdx.isValid()) return; // 将源模型索引映射为代理模型索引 QModelIndex proxyNextIdx = mProxyModel->mapFromSource(sourceNextIdx); if(!proxyNextIdx.isValid()) return; // 使用代理模型索引与TreeView交互 mTreeView->expand(proxyNextIdx); mTreeView->scrollTo(proxyNextIdx); mTreeView->selectionModel()->clear(); mTreeView->selectionModel()->select(proxyNextIdx, QItemSelectionModel::Select); }
注意事项
findNext和_findNext函数无需修改,它们基于源模型遍历所有节点的逻辑是正确的;- 确保所有传给TreeView的操作(expand、scrollTo、select)都使用代理模型索引;
- 若存在多层代理模型,可参考
nodeByProxyModelIndex中的递归映射逻辑完成索引转换。
内容的提问来源于stack exchange,提问作者Ming
相关产品推荐
相关产品推荐

