如何逐步更新QMainWindow?

问题描述 投票:4回答:3

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

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

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

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

但在9秒后,所有更改立即生效。

c++ qt qt5 qmainwindow
3个回答
6
投票

你永远不会在主线程中使用QThread::sleep(),因为它阻止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()的不良做法,如果你在某个地方看到它,不信任。


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

1
投票

在实际绘制窗口之前,应用的更改不会变为可见。通过在主UI线程上休眠,可以防止系统完成任何绘图,因此在9秒后再次离开更新功能之前,您无法看到更新。

你想要做的是有一个单独的线程,它不会阻止主UI线程每隔三秒发出一次信号,导致各个按钮出现。一定要把这些信号放在小工具上的QueuedConnection to avoid race conditions上。

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

© www.soinside.com 2019 - 2024. All rights reserved.