Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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 extends QWidget. It makes use of QGraphicsScene and QGraphicsGridLayout to add a list of QLabels in a 4x6 grid with default value for those QLabels. Without sleep, when I clicked the start button, all added QLabels show-up immediately, however, with sleep, the ScreenWidget window is completely blacked out at first and added QLabels only showed up after 5 seconds. If I replace sleep(5) with for(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:

    Peek 2021-07-15 15-18.gif

    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?


  • Lifetime Qt Champion

    @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();
    

  • Lifetime Qt Champion

    @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!


Log in to reply