I want to update a modal QProgressDialog from my worker thread. However, if I set the dialog to be modal, my application crashes (and the dialog did not show any progress). If I do not, everything goes fine (but the user can tinker around with the rest of the program, which may cause issues).
What am I doing wrong?
Minimum code sample follows:
filereader qfr;
QProgressDialog progress("Importing file.", "Cancel", 0, file_size);
connect(&qfr, &filereader::signalProgress, &progress, &QProgressDialog::setValue, Qt::QueuedConnection);
QThread worker_thread;
std::atomic<bool> success = false;
connect(&worker_thread, &QThread::started,
[&]() {
success = qfr.read_file(/* parameters */);
worker_thread.quit();});
worker_thread.start();
//progress.setWindowModality(Qt::WindowModal); // Works only fine when this line is commented !!
while (worker_thread.isRunning()) {
QApplication::processEvents();
QThread::sleep(0);
}
progress.close();
Your thread is pretty much pointless. It serves no real purpose. You could have as well just called
QApplication::processEvents
in yourread_file
method. But you shouldn't, callingprocessEvents
is bad practice.What you should do is remove that
while
loop, and make your progress dialog a member of your class. I don't really like how that lambda looks either. I would personally just usefilereader::read_file
as a slot.Note that
Qt::windowModal
blocks input to the parent window. Your progress dialog has no parent. So you would either have to callprogress->setModal(true)
, orprogress.setWindowModality(Qt::ApplicationModal);
. Or set a parent to it.Here is a small example (it is not tailor made for your application, but it should point you in the right direction):