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

QTreeView展开SSHFS挂载目录大节点时,如何显示忙碌状态?

解决QTreeView展开SSHFS目录延迟时的忙碌光标提示问题

核心思路

首次展开大目录的延迟源于SSHFS远程文件系统的IO操作阻塞了UI线程,我们需要在目录开始加载时切换为忙碌光标,加载完成后恢复正常光标。关键是利用模型的加载状态信号,而非仅依赖视图的展开信号。


针对QFileSystemModel的解决方案

如果使用Qt内置的QFileSystemModel,它自带directoryLoaded信号,可精准捕获目录加载完成的时机:

方法1:信号槽连接(无需重写视图)

// 成员变量,跟踪忙碌光标引用计数,避免多加载场景下光标异常
int m_waitCursorCount = 0;

// 连接视图展开信号,触发忙碌光标
connect(m_treeView, &QTreeView::expanded, this, [=](const QModelIndex& index) {
    auto fsModel = qobject_cast<QFileSystemModel*>(m_treeView->model());
    if (!fsModel || !fsModel->isDir(index)) return;

    QString dirPath = fsModel->filePath(index);
    // 仅对未加载的目录设置光标
    if (!fsModel->directoryLoaded(dirPath)) {
        m_waitCursorCount++;
        if (m_waitCursorCount == 1) {
            QApplication::setOverrideCursor(Qt::WaitCursor);
        }
    }
});

// 连接模型加载完成信号,恢复光标
connect(fsModel, &QFileSystemModel::directoryLoaded, this, [=](const QString&) {
    if (m_waitCursorCount > 0) {
        m_waitCursorCount--;
        if (m_waitCursorCount == 0) {
            QApplication::restoreOverrideCursor();
        }
    }
});

方法2:重写QTreeView的setExpanded方法

如果希望逻辑封装在视图内部,可继承QTreeView并重写setExpanded:

class SSHTreeView : public QTreeView {
    Q_OBJECT
public:
    using QTreeView::QTreeView;

protected:
    void setExpanded(const QModelIndex& index, bool expand) override {
        if (expand) {
            auto fsModel = qobject_cast<QFileSystemModel*>(model());
            if (fsModel && fsModel->isDir(index)) {
                QString dirPath = fsModel->filePath(index);
                if (!fsModel->directoryLoaded(dirPath)) {
                    QApplication::setOverrideCursor(Qt::WaitCursor);
                    // 单次连接,加载完成后自动断开
                    connect(fsModel, &QFileSystemModel::directoryLoaded, this,
                        [=](const QString& loadedPath) {
                            if (loadedPath == dirPath) {
                                QApplication::restoreOverrideCursor();
                            }
                        }, Qt::SingleShotConnection);
                }
            }
        }
        // 调用父类方法执行实际展开逻辑
        QTreeView::setExpanded(index, expand);
    }
};

针对自定义模型的解决方案

如果使用自定义目录模型,需要在模型中添加两个信号:

class CustomDirModel : public QAbstractItemModel {
    Q_OBJECT
signals:
    void loadingStarted(const QModelIndex& index);  // 开始加载子项时发出
    void loadingFinished(const QModelIndex& index); // 加载完成时发出
    // ... 其他模型逻辑
};

然后在视图中连接这两个信号:

connect(m_customModel, &CustomDirModel::loadingStarted, this, [=]() {
    QApplication::setOverrideCursor(Qt::WaitCursor);
});

connect(m_customModel, &CustomDirModel::loadingFinished, this, [=]() {
    QApplication::restoreOverrideCursor();
});

关键注意事项

  • 利用QApplication::setOverrideCursor和restoreOverrideCursor的栈式特性,确保光标状态正确恢复,避免多加载场景下光标异常。
  • 仅对未加载的目录设置光标,避免重复触发(比如已加载的目录再次展开时无需提示)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 22:47:07