考虑在我的主线程中的这个SLOT,由一个按钮触发,该按钮从QTreeWidgetItem中获取QTreeWidget的列表。它使用QtConcurrent::map()调用来执行较长的任务。 watcher连接到QProgressDialog以显示进度。

void Main::on_actionButton_triggered() {
    qRegisterMetaType<QVector<int> >("QVector<int>");

    //Setting up a progress dialog
    QProgressDialog progressDialog;

    //Holds the list
    QList<QTreeWidgetItem*> list;

    //Setup watcher
    QFutureWatcher<void> watcher;

    //Setting up connections
    //Progress dialog
    connect(&watcher, SIGNAL(progressValueChanged(int)), &progressDialog, SLOT(setValue(int)));
    connect(&watcher, SIGNAL(progressRangeChanged(int, int)), &progressDialog, SLOT(setRange(int,int)));
    connect(&watcher, SIGNAL(progressValueChanged(int)), ui->progressBar, SLOT(setValue(int)));
    connect(&watcher, SIGNAL(progressRangeChanged(int, int)), ui->progressBar, SLOT(setRange(int,int)));
    connect(&watcher, SIGNAL(finished()), &progressDialog, SLOT(reset()));
    connect(&progressDialog, SIGNAL(canceled()), &watcher, SLOT(cancel()));

    connect(&watcher, SIGNAL(started()), this, SLOT(processStarted()));
    connect(&watcher, SIGNAL(finished()), this, SLOT(processFinished()));

    //Gets the list filled
    for (int i = 0; i < ui->listTreeWidget->topLevelItemCount(); i++) {
        list.append(ui->listTreeWidget->topLevelItem(i));
    }

    //And start
    watcher.setFuture(QtConcurrent::map(list, processRoutine));

    //Show the dialog
    progressDialog.exec();

}

extern void processRoutine(QTreeWidgetItem* item) {
    qDebug() << item->text(4);
}


我还在UI(包含所有先前的小部件)中添加了具有相同SIGNALS / SLOTS的QProgressBar。使代码像以前一样正常工作:将显示进度对话框,并且进度栏将完全按照对话框进行更新。
相反,如果我评论

//progressDialog.exec();


或我以某种方式隐藏对话框,该过程将崩溃(并非总是如此,有时进展顺利)。查看qDebug() << item->text(4);会崩溃,并且输出显示随机混合的文本(它们应该是文件名)。另外,即使没有崩溃,即使没有显示QProgressDialog,进度条也不会自动更新。

注意:我之前在另一个函数中遇到过类似的问题,我通过设置解决了

QThreadPool::globalInstance()->setMaxThreadCount(1);


仅在Windows上,OSX可以。

那么,使所有事情正确的QProgressDialog背后的诀窍是什么?有没有一种方法可以使用QProgressBar代替QProgressDialog

注意

这是该过程顺利完成时的输出:

"C:/Users/Utente/Pictures/Originals/unsplash_52cee67a5c618_1.jpg"
"C:/Users/Utente/Pictures/Originals/photo-1428278953961-a8bc45e05f72.jpg"
"C:/Users/Utente/Pictures/Originals/photo-1429152937938-07b5f2828cdd.jpg"
"C:/Users/Utente/Pictures/Originals/photo-1429277158984-614d155e0017.jpg"
"C:/Users/Utente/Pictures/Originals/photo-1430598825529-927d770c194f.jpg"
"C:/Users/Utente/Pictures/Originals/photo-1433838552652-f9a46b332c40.jpg"

最佳答案

当您评论progressDialog.exec();
您的on_actionButton_triggered()函数以销毁progressDialog结尾,因此您的信号使用了指向无处的指针。
同样,在执行所有映射之前或之后,watcher也将被销毁,而且它不会停止线程,因此它们也无处工作。

07-26 00:31