QMessageBox dose not show the content
-
Hi,
I want to pop up a dialog telling the user to wait for processing. I use show() instead of exec() as I want the message box to return to the caller immediately (below is the code i used.). However, the message box only shows its frame but not any contents. (showing the residue of previous windows as in the attached image). Any idea how to solve this? The exec() works fine by the way but it only returns when the dialog is closed, which is not the use case here.
QMessageBox msgBox(QMessageBox::Information, tr("Request Destination"), "Waiting for reply ...", QMessageBox::Cancel, this); msgBox.setModal(true); msgBox.show(); QApplication::processEvents(); while (...) { dowork(); }
-
jsulm Lifetime Qt Championreplied to dalishi on 11 Jun 2019, 07:48 last edited by jsulm 6 Nov 2019, 07:50
@dalishi You're blocking the event loop with your while loop, no wonder dialog can't render correctly...
If you want to show dialog and and do something at the same time you can move the dowork() part to a thread. -
@dalishi
Suggest you might consider changing over to use https://doc.qt.io/qt-5/qprogressdialog.html for this, which will spin the necessary updating event loop. -
@dalishi said in QMessageBox dose not show the content:
I thought the processEvents() does the tricks
How can it if it's not inside the loop?
-
@JonB Thank you for bringing up progressdialog. Actually i have progressdialog in my program and the similar thing happens. For the first few steps, the progressdialog also does not show anything but frame only. Fortunately it shows the progress bar after a few more steps. I think it's also because the following processing code blocks the event loop. I'm just curious how the event loop works and how should we ask Qt to process the event at certain point.
-
@dalishi Either move processEvents() INSIDE the loop, or (which is better as processEvents() is a bad work around) move your background work to another thread.
-
This is untested, but should work as well. Without the nasty QProcessEvents.
QMessageBox msgBox(QMessageBox::Information, tr("Request Destination"),"Waiting for reply ...", QMessageBox::Cancel, this); msgBox.setModal(true); QMetaObject::invokeMethod(this, [=]()->void{ while (...) { dowork(); } }, Qt::QueuedConnection); msgBox.exec();
-
@jsulm Thanks very much. I finally got what you mean. processEvent() need to be in the loop for periodically getting called and processing the event. I just tried put it in the loop but I think this way messed up the normal event handling of Qt. The buttons and windows are not responsive any more as usual. So I will go for the second option as per your instruction. Thanks.
-
@J.Hilk Your solution will block the event loop as well as soon as the lambda is called, right?
-
@jsulm
actually, it doesn't work at all, from my quick test I made.I'm not entirely sure why...
8/12