如何逐步更新QMainWindow?

时间:2018-08-03 09:46:27

标签: c++ qt qt5 qmainwindow

我想逐步更新QMainWindow。我使用睡眠方法,但看不到变化。我想每3秒查看一次更改。

void MainWindow::updateScreen()
{
    ui->pushButton1->show();
    QThread::sleep(3);

    ui->pushButton2->show();
    QThread::sleep(3);

    ui->pushButton3->show();
    QThread::sleep(3);
}

但是9秒钟后,所有更改都会立即生效。

3 个答案:

答案 0 :(得分:6)

您永远不要在主线程中使用QThread::sleep(),因为它会阻止GUI通知事件,从而导致GUI行为不正确,其他问题也可以正确解决,因此我不会将其专用于我,我的回答将是集中为您提供我认为最适合使用QTimeLine的解决方案:

const QWidgetList buttons{ui->pushButton1, ui->pushButton2, ui->pushButton3};

QTimeLine *timeLine =  new QTimeLine( 3000*buttons.size(), this);
timeLine->setFrameRange(0, buttons.size());
connect(timeLine, &QTimeLine::frameChanged, [buttons](int i){
    buttons[i-1]->show();
});
connect(timeLine, &QTimeLine::finished, timeLine, &QTimeLine::deleteLater);
timeLine->start();

我不建议使用processEvents(),因为许多初学者会滥用它,认为它是魔术解决方案,例如the @cbuchart solution不正确,因为解决了眼前的问题,但没有解决背景问题,例如,尝试在这9秒钟内更改窗口的大小。你可以做到吗?好吧,不是因为QThread :: sleep()阻塞了。

请考虑在GUI线程中使用QThread::sleep()不好的做法,如果您在某处看到它,请相信。

答案 1 :(得分:4)

我建议您使用QTimer::singleShot静态方法。

void MainWindow::updateScreen()
{
    QTimer::singleShot(3000, [this](){ui->pushButton1->show();});
    QTimer::singleShot(6000, [this](){ui->pushButton2->show();});
    QTimer::singleShot(9000, [this](){ui->pushButton3->show();});
}

答案 2 :(得分:1)

在实际绘制窗口之前,看不到应用的更改。通过在主UI线程上休眠,可以完全阻止系统进行任何绘制,因此,直到9秒后再次退出更新功能,您才能看到更新的发生。

您要做的是有一个 separate 线程,该线程不会阻塞主UI线程每三秒钟发出一次信号,从而导致各个按钮出现。确保将这些信号放在小部件的QueuedConnection to avoid race conditions上。

或者,如果您不想浪费线程,则还可以有一个连续更新事件,该事件检查自当前更新周期开始以来已经经过了多少时间,并仅在经过足够的时间后才显示相应的按钮。 。 QTimer class提供了一种方便的方法。只要确保您不会通过执行大量计算或在同一线程上休眠来阻止事件循环,否则您将再次无法看到更新。