Solved why is widget.show() blocked if placing long-running code right after it?
-
I ran into a weird situation.
Here is the slot function will be called when a button in the main window is clicked.
void MainWindow::on_startBtn_clicked() { ScreenWidget * screen = new ScreenWidget(nullptr); screen->startupScreen(2, 6); screen->show(); sleep(5); }
ScreenWidget
is a custom widget that extendsQWidget
. It makes use ofQGraphicsScene
andQGraphicsGridLayout
to add a list of QLabels in a 4x6 grid with default value for those QLabels. Withoutsleep
, when I clicked the start button, all added QLabels show-up immediately, however, withsleep
, theScreenWidget
window is completely blacked out at first and added QLabels only showed up after 5 seconds. If I replacesleep(5)
withfor(int i = 0; i < 1000000000; i++){}
, similar situation occurred,ScreenWidget
blacked out at first, then its contents (a 4x6 grid of QLabels) show up after the loop finished running. Below is the blocking behaviour I was describing:I've read the doc for
void QWidget::show()
but still couldn't understanding why the blocking happened.So why did the blocking happen (
show
is asynchronous)? How do I prevent the black out screen? -
@hyperlight said in why is widget.show() blocked if placing long-running code right after it?:
So why did the blocking happen (show is asynchronous)? How do I prevent the black out screen?
show() is asynchronous, but just after you call it you block the Qt event loop! This is something you should NEVER do in the main thread (GUI thread) if you want to keep your UI responsive. As long as event loop is blocked events will not be processed, so UI will be blocked.
"How do I prevent the black out screen?" - move long lasting tasks in other threads. -
Hey, guy!
sleep() make the thread to sleep and do nothings, so it blocked the current thread.
And (show is asynchronous)?,I think you may do somethings asychronous in the ScreenWidget 's ctor or showEvent.
you may need to know Modeless dialogs.
A modeless dialog is a dialog that operates independently of other windows in the same application, and to allow the user to interact with both the application's main window and with the dialog.Modeless dialogs are displayed using show(), which returns control to the caller immediately.As "How do I prevent the black out screen?"
You can use the local event loop.QEventLoop loop; QTimer::singleShot(5000, &loop, &QEventLoop::quit); loop.exec();
-
@hyperlight said in why is widget.show() blocked if placing long-running code right after it?:
So why did the blocking happen (show is asynchronous)? How do I prevent the black out screen?
show() is asynchronous, but just after you call it you block the Qt event loop! This is something you should NEVER do in the main thread (GUI thread) if you want to keep your UI responsive. As long as event loop is blocked events will not be processed, so UI will be blocked.
"How do I prevent the black out screen?" - move long lasting tasks in other threads. -
@hyperlight
Further to my colleague @jsulm.If it helps, don't think of
QWidget::show()
actually showing the widget. Think of it as marking the widget to be shown at a later time. And that showing only happens the next time the main Qt event loop is allowed to run. Not allowed to run => no actual show!