Consider this SLOT
, in my main thread, trigged by a button, which takes a list of QTreeWidgetItem
from a QTreeWidget
. It uses a QtConcurrent::map()
call to execute a long task. The watcher
connects to a QProgressDialog
to show progress.
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);
}
I also added, in the UI (which holds all the previous widgets), a QProgressBar
with the same SIGNALS/SLOTS. Keeping the code like the previous works as expected: the progress dialog shows up, and the progress bar updates exactly as the dialog.
Instead, if I comment the
//progressDialog.exec();
or I hide the dialog in some way, the process crashes (not always, sometimes it goes well). Looking at qDebug() << item->text(4);
it crashes and the output shows randomly mixed text (they are supposed to be filenames). Also, the progressbar does not update itself when the QProgressDialog
is not shown, even if the computation does not crash.
Note: I experienced a similar problem before in another function, and I solved it by setting
QThreadPool::globalInstance()->setMaxThreadCount(1);
on Windows only, OSX was ok.
So, what's the trick behind the QProgressDialog
that makes all the things right? Is there a way I can use the QProgressBar
instead of the QProgressDialog
?
NOTE
This is the output when the process completes without troubles:
"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"