选中项时失效QSortFilterProxyModel过滤器致崩溃问题求助
Qt 5.15.3 文件浏览器代理模型切换目录崩溃问题
场景说明
在Qt 5.15.3中开发游戏文件系统的文件浏览器,左侧为目录树视图,右侧为文件表格视图。选中树中目录时,表格需显示该目录下的文件(不含嵌套子目录)。
为两个视图分别实现QSortFilterProxyModel:
- 树视图代理的
filterAcceptsRow仅判断项是否为目录; - 表格视图代理因切换目录时需变更根索引,逻辑更复杂。
核心代码实现
目录切换触发逻辑
void FileSystemBrowserWidget::onDirectoryActivated(const QModelIndex& index) { // Since the proxy model filters based on the source model, we get // the source index to use for filtering. The index we have // been passed is from the tree view's proxy model. const QModelIndex sourceIndex = m_treeProxyModel->mapToSource(index); // Tell the table's proxy model about this new root. m_tableProxyModel->setRootForFiltering(sourceIndex); // Set the table view's root to display from. // The table view shows the proxy model, so we map to this model. m_fileSystemTableView->setRootIndex(m_tableProxyModel->mapFromSource(sourceIndex)); }
表格代理设置过滤根索引
void FileSystemBrowserTableProxyModel::setRootForFiltering(const QModelIndex& sourceIndex) { if (m_rootForFiltering == sourceIndex) { return; } m_rootForFiltering = sourceIndex; invalidateFilter(); }
表格代理过滤规则
bool FileSystemBrowserTableProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent) const { QAbstractItemModel* src = sourceModel(); const QModelIndex srcIndex = src->index(sourceRow, 0, sourceParent); if (srcIndex == m_rootForFiltering) { // Always allowed, or children don't show up. return true; } // Allow if this index represents a file and not a directory. return itemAtIndexIsAFile(srcIndex); }
问题现象
过滤逻辑正常,但选中表格项后切换树目录时,终端会重复9次报错QSortFilterProxyModel: index from wrong model passed to mapFromSource,随后崩溃,调用栈如下:
___lldb_unnamed_symbol11407 (@___lldb_unnamed_symbol11407:41) QSortFilterProxyModel::flags(QModelIndex const&) const (@QSortFilterProxyModel::flags(QModelIndex const&) const:43) QAbstractItemView::focusInEvent(QFocusEvent*) (@QAbstractItemView::focusInEvent(QFocusEvent*):41) QWidget::event(QEvent*) (@QWidget::event(QEvent*):763) QFrame::event(QEvent*) (@QFrame::event(QEvent*):14) QApplicationPrivate::notify_helper(QObject*, QEvent*) (@QApplicationPrivate::notify_helper(QObject*, QEvent*):42) ... call stack continues ...
排查情况
- 未发现自身代码直接触发该错误,推测是代理模型使用不当;
- 移除
invalidateFilter调用则无此问题,但会导致目录作为表格根时子文件无法显示; - 无法开启
recursiveFilteringEnabled,否则含文件的目录会显示在表格中; - 开发环境:Kubuntu。
内容的提问来源于stack exchange,提问作者NoodleCollie
相关产品推荐
相关产品推荐

