You need to enable JavaScript to run this app. 为什么QSortFilterProxyModel搭配QStandardItemModel时TreeView出现额外空白行
优惠活动
大模型
产品
解决方案
定价
更多

为什么QSortFilterProxyModel搭配QStandardItemModel时TreeView出现额外空白行

问题原因
  • 非UI线程操作数据模型
    Qt所有模型视图相关类都不是线程安全的,你使用QtConcurrent::run在后台线程执行buildFileTree方法,直接修改QStandardItemModel的内部数据,会导致模型内部索引、行计数混乱,代理模型读取源模型数据时会读到大量无效条目,最终显示为空白行,这是出现空白行的核心原因。
  • 代理模型构造未正确初始化父类
    FileFilterModel的构造函数没有显式调用父类QSortFilterProxyModel的构造函数,会导致父类内部状态未正确初始化,过滤逻辑异常。
  • 过滤逻辑重复且混用过时API
    filterAcceptsRow实现中,既使用了新版的filterRegularExpression做匹配,最后又重复用已过时的filterRegExp做二次判断,逻辑冗余还可能出现匹配冲突;同时递归判断子项匹配后已经返回true,后面的匹配逻辑完全多余。
修复方案

1. 调整模型修改逻辑到UI线程

如果扫描的文件夹体积不大,可以直接去掉异步逻辑,在UI线程执行模型修改操作;如果文件夹层级深、文件多,可以把后台扫描文件结构和修改模型的逻辑拆分,扫描完成后通过信号槽把结果投递到UI线程再创建节点修改模型,避免跨线程操作模型的问题:

// 修改MainWindow的on_actionManage_Folders_triggered方法
void MainWindow::on_actionManage_Folders_triggered()
{
    ui->progressLabel->setText("Adding folder");
    QString folderName = QFileDialog::getExistingDirectory(this, "Select Folder", QDir::homePath());
    if(folderName.isEmpty()) return;
    // 小文件夹直接在UI线程执行即可
    filemodel->buildFileTree(folderName);
    ui->progressLabel->setText("Folder added");
}

2. 修复FileFilterModel的构造函数

FileFilterModel::FileFilterModel(QObject *parent)
    : QSortFilterProxyModel(parent) // 显式调用父类构造完成初始化
{
}

3. 简化过滤逻辑,统一使用新版API

bool FileFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
    QModelIndex index0 = sourceModel()->index(sourceRow, filterKeyColumn(), sourceParent);
    if (!index0.isValid())
        return false;

    // 先判断当前节点是否匹配过滤规则
    QString currentText = sourceModel()->data(index0).toString();
    if (currentText.contains(filterRegularExpression()))
        return true;

    // 递归判断子节点是否有匹配,有匹配就保留当前父节点
    int childRowCount = sourceModel()->rowCount(index0);
    for (int i = 0; i < childRowCount; ++i) {
        if (filterAcceptsRow(i, index0))
            return true;
    }

    // 自身和子节点都不匹配则过滤当前行
    return false;
}
额外优化建议

初始化代理模型时显式设置过滤列和过滤角色,避免默认值异常:

// 在MainWindow构造函数中添加如下代码
fileFilterModel->setFilterKeyColumn(0);
fileFilterModel->setFilterRole(Qt::DisplayRole);

内容的提问来源于stack exchange,提问作者Janet Wu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 20:36:05