class CustomSysmodel : public QFileSystemModel { Q_OBJECT public: CustomSysmodel(QWidget *parent = Q_NULLPTR) : QFileSystemModel(parent) , m_limit(100) , m_timer(new QTimer(this))//m_timer 使用 this 作为其父对象创建的,在 CustomSysmodel 对象被删除时自动删除(不确定) { connect(m_timer, &QTimer::timeout, this, &CustomSysmodel::loadMoreFiles);//直接在构造函数中植入计时器 m_timer->setInterval(2000); } void CustomSysmodel::fetchFiles(const QString &path) { emit started(); QThread *thread = new QThread; //**********************需要释放空间 FileSystemWorker *worker = new FileSystemWorker; worker->moveToThread(thread); connect(thread, &QThread::started, worker, this, worker, path { worker->fetchFiles(path); }); connect(worker, &FileSystemWorker::fileFound, this, &CustomSysmodel::fileFound); connect(worker, &FileSystemWorker::finished, thread, &QThread::quit); connect(worker, &FileSystemWorker::finished, worker, &FileSystemWorker::deleteLater); connect(thread, &QThread::finished, thread, &QThread::deleteLater); connect(worker, &FileSystemWorker::finished, this, &CustomSysmodel::finished); thread->start();//启动线程 QMetaObject::invokeMethod(thread, "wait", Qt::QueuedConnection);//另一种写法,还是不能边构建model边描画 delete thread; delete worker; } } class FileSystemWorker : public QObject { Q_OBJECT public: FileSystemWorker(QObject *parent = nullptr) : QObject(parent) {} public slots: void fetchFiles(const QString &path) { QFileInfoList files = QDir(path).entryInfoList(QDir::Files); foreach (const QFileInfo &fileInfo, files) { cout<<"xianc"<<endl; emit fileFound(fileInfo.absoluteFilePath()); } } signals: void started(); void finished(); void fileFound(const QString &filePath); }; 如上述代码所示:qtreeview使用继承自Qfilesystemmodel的自定义模型,想要实现单独线程读取文件,再发送给主线程,目的是为了访问百万级文件时,可以流畅访问。 但现在只有全部加载完主线程才能运行,分析原因,给出完整的修改方案
时间: 2024-02-21 10:56:55 浏览: 77
通过QFileSystemModel 自定义文件夹浏览器
5星 · 资源好评率100%
问题分析:
当前的实现方式是在主线程中构建了一个新的线程,然后在新线程中执行文件读取操作。但是,在主线程中调用 `fetchFiles` 函数时,会直接启动新线程进行文件读取操作,而不是等待用户在界面上操作后再触发。这样会导致主界面在文件读取的过程中处于卡顿状态,用户体验不好。
解决方案:
1. 将 `fetchFiles` 函数改为槽函数,并在其中添加 `QRunnable` 对象,使用 `QThreadPool` 进行调度,避免直接使用线程。
2. 在 `CustomSysmodel` 类中添加一个成员变量 `QThreadPool* m_threadPool`,用于管理线程池。
3. 在 `CustomSysmodel` 的构造函数中,初始化 `m_threadPool` 成员变量。
4. 将 `FileSystemWorker` 类中的 `fetchFiles` 函数改为 `run` 函数,并继承 `QRunnable` 类。
5. 修改 `CustomSysmodel` 中的 `fetchFiles` 槽函数的实现,使用 `QThreadPool` 来调度 `FileSystemWorker` 对象的执行。
修改后的代码如下:
```cpp
class CustomSysmodel : public QFileSystemModel {
Q_OBJECT
public:
CustomSysmodel(QWidget *parent = Q_NULLPTR) : QFileSystemModel(parent),
m_limit(100),
m_timer(new QTimer(this)),
m_threadPool(new QThreadPool(this))
{
connect(m_timer, &QTimer::timeout, this, &CustomSysmodel::loadMoreFiles);
m_timer->setInterval(2000);
}
public slots:
void fetchFiles(const QString &path)
{
emit started();
FileSystemWorker* worker = new FileSystemWorker;
connect(worker, &FileSystemWorker::fileFound, this, &CustomSysmodel::fileFound);
connect(worker, &FileSystemWorker::finished, this, &CustomSysmodel::finished);
worker->setPath(path);
m_threadPool->start(worker);
}
private:
int m_limit;
QTimer *m_timer;
QThreadPool *m_threadPool;
};
class FileSystemWorker : public QObject, public QRunnable {
Q_OBJECT
public:
FileSystemWorker(QObject *parent = nullptr) : QObject(parent) {}
void setPath(const QString& path) { m_path = path; }
void run() override
{
QFileInfoList files = QDir(m_path).entryInfoList(QDir::Files);
foreach (const QFileInfo &fileInfo, files) {
emit fileFound(fileInfo.absoluteFilePath());
}
emit finished();
}
signals:
void started();
void finished();
void fileFound(const QString &filePath);
private:
QString m_path;
};
```
这样,我们就将文件读取操作放入了线程池中进行调度,避免了主线程的卡顿。同时使用 `QRunnable` 代替了直接使用线程,使得代码更加简洁易读。
阅读全文