无法在 window 中显示任何内容之前和 window 完善后进行介绍
unable to make an intro before showing anything in the window and after the window is polished
我正在使用 Unix 19.02 和 Qt 5.13.0。
我想在 window 中显示任何内容之前先介绍一下我的应用程序。所以,我的想法是让 QPainter 在 while 循环中改变背景颜色。我试了太多次,我在时间上遇到了问题:"When is the moment or the event that I should make the qpainter start the introduction?"。我搜索并发现最好的办法是重新实现这个功能:
void showEvent(QShowEvent* event) {...}
在该函数内,我调用了 "repaint()",它将完成所有介绍。
我尝试了所有这些方法:
- 在 "paintEvent" 函数中创建 while 循环。
- 在 "paintEvent" 函数之外创建 while 循环,每次我们更改背景颜色时我都会调用 "repaint()"。当然,我为计算机设置了一个小超时以减慢它的速度。
-注意:使用上面这两种方式,出现了window,但是它的背景颜色是黑色,什么也没有出现,直到介绍完颜色才变!
- 最近,一个不使用 "QPainter" 的 while 循环改为使用样式表,并且在我们更改 "background-color" 属性 之后。我们称:
ui->centeralWidget->style->polish(ui->centeralWidget);
最后一种方法,强制 window 在介绍完全完成之前不显示(执行介绍需要 5 秒,while 循环)。这是代码:
QString ss; // for opacity
QString ss_prefix = "background-color: rgba(255, 255, 255, ";
QString ss_suffix = ");";
while(i<=50) {
i++;
Opacity += 5;
qDebug() << "Changing opacity : " << ss_prefix+std::to_string(Opacity).c_str()+ss_suffix;
ui->centralWidget->setStyleSheet(
ss_prefix+std::to_string(Opacity).c_str()+ss_suffix);
ui->centralWidget->style()->polish(ui->centralWidget);
QThread::currentThread()->msleep(100); // 100 * 50 = 5000/1000 = 5 seconds to execute!
}
尽管如此,还有其他方法可以介绍,但我真的很想知道发生了什么并解决这个问题!
最后一个等式用于计算执行时间:
100(sleep) * 50(The code will get executed 50 times) = 5000 / 1000 (it is in milli, so divide by 1000) = 5 seconds
Wish you understood my situation.
你没有提供完整的代码,所以我在这里部分猜测。
在开始动画之前,您需要等待主应用程序事件循环开始。如果您从 QMainWindow
(或任何您的顶级 QWidget
是)构造函数调用该动画例程(最后带有 msleep()
),则主 window 永远不会有机会展示自己(直到动画完成)。
如果我是对的,您可以考虑从第一个 QWidget::showEvent()
开始制作动画,方法是使用 bool
标志来了解第一场演出的时间。另一种方法是在构造函数中启动一个 QTimer::singleShot(0, this, &MainWindow::animate)
(一旦主事件循环开始,计时器就会触发)。还有其他方法,但要点是你需要让QApplication事件循环运行和window已经初始化。
说了这么多,我可能会采取不同的方法,可能会使用 QSplashScreen
或自定义 QWidget 在加载主 window 之前或同时显示动画背景。
此外,查看 QString
template/replacement 系统,特别是 arg()
方法以及如何使用它们来简化字符串构造。
作为@MaximPaperno points out, the problem is while-loop + msleep() since they block the eventloop preventing the GUI from working normally. For these cases, Qt provides strategies such as QTimer, QXAnimation, etc. In this case a simple solution is to use QVariantAnimation
:
*.h
// ...
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private Q_SLOTS:
void applyOpacity(const QVariant &value);
// ...
*.cpp
// ...
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QVariantAnimation *animation = new QVariantAnimation(this);
animation->setStartValue(0);
animation->setEndValue(255);
animation->setDuration(5 * 1000);
connect(animation, &QVariantAnimation::valueChanged, this, &MainWindow::applyOpacity);
animation->start(QAbstractAnimation::DeleteWhenStopped);
}
// ...
void MainWindow::applyOpacity(const QVariant & value)
{
bool ok;
int opacity = value.toInt(&ok);
if(ok) {
QString qss = QString("background-color: rgba(255, 255, 255, %1)").arg(opacity);
ui->centralWidget->setStyleSheet(qss);
}
}
这是一个微不足道的情况。请先显示欢迎 window。当它关闭时,显示你的主要 window。使用信号来实现它。
我正在使用 Unix 19.02 和 Qt 5.13.0。
我想在 window 中显示任何内容之前先介绍一下我的应用程序。所以,我的想法是让 QPainter 在 while 循环中改变背景颜色。我试了太多次,我在时间上遇到了问题:"When is the moment or the event that I should make the qpainter start the introduction?"。我搜索并发现最好的办法是重新实现这个功能:
void showEvent(QShowEvent* event) {...}
在该函数内,我调用了 "repaint()",它将完成所有介绍。 我尝试了所有这些方法:
- 在 "paintEvent" 函数中创建 while 循环。
- 在 "paintEvent" 函数之外创建 while 循环,每次我们更改背景颜色时我都会调用 "repaint()"。当然,我为计算机设置了一个小超时以减慢它的速度。 -注意:使用上面这两种方式,出现了window,但是它的背景颜色是黑色,什么也没有出现,直到介绍完颜色才变!
- 最近,一个不使用 "QPainter" 的 while 循环改为使用样式表,并且在我们更改 "background-color" 属性 之后。我们称:
ui->centeralWidget->style->polish(ui->centeralWidget);
最后一种方法,强制 window 在介绍完全完成之前不显示(执行介绍需要 5 秒,while 循环)。这是代码:
QString ss; // for opacity
QString ss_prefix = "background-color: rgba(255, 255, 255, ";
QString ss_suffix = ");";
while(i<=50) {
i++;
Opacity += 5;
qDebug() << "Changing opacity : " << ss_prefix+std::to_string(Opacity).c_str()+ss_suffix;
ui->centralWidget->setStyleSheet(
ss_prefix+std::to_string(Opacity).c_str()+ss_suffix);
ui->centralWidget->style()->polish(ui->centralWidget);
QThread::currentThread()->msleep(100); // 100 * 50 = 5000/1000 = 5 seconds to execute!
}
尽管如此,还有其他方法可以介绍,但我真的很想知道发生了什么并解决这个问题!
最后一个等式用于计算执行时间:
100(sleep) * 50(The code will get executed 50 times) = 5000 / 1000 (it is in milli, so divide by 1000) = 5 seconds Wish you understood my situation.
你没有提供完整的代码,所以我在这里部分猜测。
在开始动画之前,您需要等待主应用程序事件循环开始。如果您从 QMainWindow
(或任何您的顶级 QWidget
是)构造函数调用该动画例程(最后带有 msleep()
),则主 window 永远不会有机会展示自己(直到动画完成)。
如果我是对的,您可以考虑从第一个 QWidget::showEvent()
开始制作动画,方法是使用 bool
标志来了解第一场演出的时间。另一种方法是在构造函数中启动一个 QTimer::singleShot(0, this, &MainWindow::animate)
(一旦主事件循环开始,计时器就会触发)。还有其他方法,但要点是你需要让QApplication事件循环运行和window已经初始化。
说了这么多,我可能会采取不同的方法,可能会使用 QSplashScreen
或自定义 QWidget 在加载主 window 之前或同时显示动画背景。
此外,查看 QString
template/replacement 系统,特别是 arg()
方法以及如何使用它们来简化字符串构造。
作为@MaximPaperno points out, the problem is while-loop + msleep() since they block the eventloop preventing the GUI from working normally. For these cases, Qt provides strategies such as QTimer, QXAnimation, etc. In this case a simple solution is to use QVariantAnimation
:
*.h
// ...
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private Q_SLOTS:
void applyOpacity(const QVariant &value);
// ...
*.cpp
// ...
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QVariantAnimation *animation = new QVariantAnimation(this);
animation->setStartValue(0);
animation->setEndValue(255);
animation->setDuration(5 * 1000);
connect(animation, &QVariantAnimation::valueChanged, this, &MainWindow::applyOpacity);
animation->start(QAbstractAnimation::DeleteWhenStopped);
}
// ...
void MainWindow::applyOpacity(const QVariant & value)
{
bool ok;
int opacity = value.toInt(&ok);
if(ok) {
QString qss = QString("background-color: rgba(255, 255, 255, %1)").arg(opacity);
ui->centralWidget->setStyleSheet(qss);
}
}
这是一个微不足道的情况。请先显示欢迎 window。当它关闭时,显示你的主要 window。使用信号来实现它。