在单独的线程上填充、填充QTreeView树

Populating, Filling QTreeView tree on a separate thread

本文关键字:填充 QTreeView 单独 线程      更新时间:2023-10-16

我试图在一个单独的线程上填充一个QTreeView对象。我想要写入的信息是一个文件夹+文件列表,是在网络驱动器上。遍历子目录需要花费很多时间,所以我不想在此操作期间阻塞Gui线程。

下面是我的代码:
class Worker : public QObject
{
    Q_OBJECT
public slots:
    void doWork(QString &parameter){
        QString data;
        QDirIterator it(parameter, QStringList() << "*.xml", QDir::Files, QDirIterator::Subdirectories);
        while (it.hasNext()) {
            QString currentFile = it.next();
            emit resultReady(currentFile);
        }
    }
    signals:
        void resultReady(QString &result);
    };
class iUSMDatabaseComposerWindow:public QMainWindow{
        Q_OBJECT
        ...
        QThread workerThread;
        QEventLoop loop;
    public:
        iUSMDatabaseComposerWindow(){
        Worker *worker = new Worker;
        worker->moveToThread(&workerThread);
        bool success = connect(&workerThread, SIGNAL(finished()), worker, SLOT(deleteLater())); assert(success);
        success = connect(this, SIGNAL(getFilesInFolder(QString &)), worker, SLOT(doWork(QString &))); assert(success);
        success = connect(worker, SIGNAL(resultReady(QString &)), this, SLOT(appendToTree(QString &))); assert(success);
        //For Qt5 : connect( &workerThread, &QThread::started, &loop, &QEventLoop::quit );
        success = connect( &workerThread, SIGNAL( started() ), &loop, SLOT( quit() ), Qt::DirectConnection ); assert(success);
        workerThread.start();
        loop.exec(); // wait for thread initialization
        QString targetFolder (TARGETFOLDER);
        emit getFilesInFolder(targetFolder);
    }
    signals:
        void getFilesInFolder(QString &folderToProcess);
    private slots:
        void appendToTree(QString &file);

我所经历的是connect()是成功的,但工人的插槽(doWork)从未被emit getFilesInFolder(targetFolder)调用。我注意到,如果我在连接到doWork()插槽时添加Qt::DirectConnection,它确实会调用它。

这里可能有什么问题?

尝试在线程初始化完成后发出一个信号:

QThread t;
// connect here
QEventLoop loop;
connect( &t, &QThread::started, &loop, &QEventLoop::quit );
// for Qt4: connect( &t, SIGNAL( started() ), &loop, SLOT( quit() ) );
t.start();
loop.exec(); // wait for thread initialization
emit YourSignal();

你的问题:你在线程初始化完成之前发出信号。QThread在创建线程后启动事件循环。但是在您的情况下,事件循环不能及时初始化,所以您的emit什么也不做。

我终于能够通过直接连接到工人的start()信号来调用工人的doWork()插槽:

success = connect(workerThread, SIGNAL(started()), worker, SLOT(doWork())); assert(success);

可以,但是不能回答原来问题的问题