简体   繁体   English

QWidget不显示QLabel

[英]QWidget not displaying the QLabel

I have a QWidget which I want to use like a Dialog on top of another QWidget. 我有一个QWidget,要像另一个QWidget上的Dialog一样使用。

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. 如果我将代码复制到其他区域(例如复制到MainWindow构造函数),它将正确显示并带有消息。

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. 由于您是在QObject插槽中创建并显示此窗口小部件,然后在从插槽返回之前关闭该窗口小部件,因此在Qt执行所有指令的过程中,最后一个窗口close ,因此窗口小部件消失了从视图。

Underneath your slot, Qt is running in an event loop. 在您的广告位下方,Qt正在事件循环中运行。 Since control is never returned to the event loop, Qt never has an opportunity to render the graphics you've requested of it. 由于控制永远不会返回到事件循环,因此Qt永远不会有机会呈现您要求的图形。

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 . 如果您希望Qt渲染您在插槽中所做的任何更改,则在返回事件循环之前,必须调用processEvents

Without doing so, you won't see those changes until control passes back to the Qt event loop . 如果不这样做,您将看不到这些更改, 直到控制权传递回Qt事件循环为止

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. 因此,这里发生的是,由于您还要在插槽末端关闭窗口小部件,因此Qt将创建窗口小部件,渲染其内容,然后立即将其关闭,您将看不到任何东西。

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. 这样做的原因是,Qt可以对可见的内容,不可见的内容进行计算,对呈现的内容等保持精明,仅决定绘制必要的内容。

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. 因此,您需要将processEvents放入回调插槽中。

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. 至于为什么显示窗口小部件窗口而不显示内容的原因,这很可能是因为在创建窗口小部件时Qt将消息发送到窗口管理器(在本例中为MS Windows),该窗口管理器将创建一个窗口,Qt可以在该窗口上呈现其内容。

So you see the result of Windows creating a new window for Qt, but nothing from Qt painting on that window itself. 因此,您会看到Windows为Qt创建一个新窗口的结果,但是在该窗口本身上进行Qt绘制不会产生任何结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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