You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

选中项时失效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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 15:02:48