如何逐步更新QMainWindow?
How to update QMainWindow step by step?
我想逐步更新我的 QMainWindow。我使用睡眠方法,但看不到变化。我想每 3 秒查看一次更改。
void MainWindow::updateScreen()
{
ui->pushButton1->show();
QThread::sleep(3);
ui->pushButton2->show();
QThread::sleep(3);
ui->pushButton3->show();
QThread::sleep(3);
}
但是 9 秒后,所有更改都会立即应用。
在实际绘制 window 之前,应用的更改不会变得可见。通过在主线程 UI 上休眠,您可以完全阻止系统进行任何绘制,因此您无法看到更新的发生,直到您在 9 秒后再次离开更新功能。
您想要做的是有一个 单独的 线程不阻塞主 UI 线程每三秒发出一次信号,使各个按钮出现。确保将这些信号放在小部件的 QueuedConnection to avoid race conditions 上。
或者,如果你不想浪费一个线程,你也可以有一个连续的更新事件,检查自当前更新周期开始以来已经过了多少时间,只有在足够的时间后才显示相应的按钮已经过去了。 QTimer class 提供了一种方便的方法。请确保您不会通过执行繁重的计算或在同一个线程上休眠来阻塞事件循环,否则您将再次无法看到更新。
你永远不会在主线程中使用 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 秒内更改 window 的大小。你可以做到吗?好吧,不是因为 QThread::sleep() 阻塞了。
考虑在 GUI 线程中使用 QThread::sleep()
的 错误做法,如果您在某处看到它,请不信任。
我建议您使用 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();});
}
我想逐步更新我的 QMainWindow。我使用睡眠方法,但看不到变化。我想每 3 秒查看一次更改。
void MainWindow::updateScreen()
{
ui->pushButton1->show();
QThread::sleep(3);
ui->pushButton2->show();
QThread::sleep(3);
ui->pushButton3->show();
QThread::sleep(3);
}
但是 9 秒后,所有更改都会立即应用。
在实际绘制 window 之前,应用的更改不会变得可见。通过在主线程 UI 上休眠,您可以完全阻止系统进行任何绘制,因此您无法看到更新的发生,直到您在 9 秒后再次离开更新功能。
您想要做的是有一个 单独的 线程不阻塞主 UI 线程每三秒发出一次信号,使各个按钮出现。确保将这些信号放在小部件的 QueuedConnection to avoid race conditions 上。
或者,如果你不想浪费一个线程,你也可以有一个连续的更新事件,检查自当前更新周期开始以来已经过了多少时间,只有在足够的时间后才显示相应的按钮已经过去了。 QTimer class 提供了一种方便的方法。请确保您不会通过执行繁重的计算或在同一个线程上休眠来阻塞事件循环,否则您将再次无法看到更新。
你永远不会在主线程中使用 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 秒内更改 window 的大小。你可以做到吗?好吧,不是因为 QThread::sleep() 阻塞了。
考虑在 GUI 线程中使用 QThread::sleep()
的 错误做法,如果您在某处看到它,请不信任。
我建议您使用 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();});
}