简体   繁体   中英

QWidget not displaying the QLabel

I have a QWidget which I want to use like a Dialog on top of another QWidget.

What I'm trying to do is a simple "Please wait while yadda yadda..." dialog with no buttons.

The code section is as follows:

void NewWindow::on_combobox_New_currentIndexChanged(int index) //slot function
{
    QWidget* box = new QWidget();
    box->setWindowModality(Qt::ApplicationModal);
    box->setWindowTitle("Wait...");

    QHBoxLayout* layout = new QHBoxLayout();
    box->setLayout(layout);
    QLabel* lbl = new QLabel();
    lbl->setText("Loading...");
    layout->addWidget(lbl);

    box->show();


    for (int var = 0; var < st.size(); ++var)
    {
        //Some heavy lifting here
    }

    box->close();
}

Normally I would expect this dialogue box to appear with the proper text and disappear after the loop ends. In fact it does that too but with one difference: The label does not display. The widget looks empty. Then disappears.

QWidget标签未显示

If I copy the code into a different area (for example to the MainWindow constructor) it displays properly with the message in it.

QWidget标签显示正确

I sense that the loop blocks the draw operation but then the widget itself should be missing too. Why it is only the label eludes me.

Thanks for any insight.

Since you are creating and displaying this widget in a QObject slot, and then before returning from the slot, closing the widget, by the time Qt goes through the process of executing all your instructions, the last one is close , and so the widget disappears from view.

Underneath your slot, Qt is running in an event loop. Since control is never returned to the event loop, Qt never has an opportunity to render the graphics you've requested of it.

When you create widgets, add labels, etc, you are actually registering a bunch of commands with the event loop, which will only later be processed.

If you want Qt to render any changes you have made whilst in a slot , before returning to the event loop, you have to call processEvents .

Without doing so, you won't see those changes until control passes back to the Qt event loop .

So what is happening here, is that since you're also closing the widget at the end of your slot, Qt will create the widget, render its contents, and then immediately close it, and you won't see anything.

The reason for this is so that Qt can do calculations on what is visible, what isn't, be smart about what it renders etc, and only decide to draw what is necessary.

If it just rendered everything immediately, without waiting for control to return to it so it can process the "next batch of updates", it would likely be horribly inefficient.

So you need to put processEvents inside your callback slot.

void NewWindow::on_combobox_New_currentIndexChanged(int index) //slot function
{
    QWidget* box = new QWidget();
    box->setWindowModality(Qt::ApplicationModal);
    box->setWindowTitle("Wait...");

    QHBoxLayout* layout = new QHBoxLayout();
    box->setLayout(layout);
    QLabel* lbl = new QLabel();
    lbl->setText("Loading...");
    layout->addWidget(lbl);

    box->show();
    QCoreApplication::processEvents(); // cause the box to be displayed

    for (int var = 0; var < st.size(); ++var)
    {
        //Some heavy lifting here

        // if you do anything here to change the widget, such as 
        // updating a progress bar, you need to `processEvents` again

        QCoreApplication::processEvents();
    }

    box->close();
}

As for why the widget window appears, but not the contents, this is likely because when creating the widget Qt sends a message to the Window Manager (in this case MS Windows), which will create the window on which Qt can render its contents.

So you see the result of Windows creating a new window for Qt, but nothing from Qt painting on that window itself.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM