无法在 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()",它将完成所有介绍。 我尝试了所有这些方法:

  1. 在 "paintEvent" 函数中创建 while 循环。
  2. 在 "paintEvent" 函数之外创建 while 循环,每次我们更改背景颜色时我都会调用 "repaint()"。当然,我为计算机设置了一个小超时以减慢它的速度。 -注意:使用上面这两种方式,出现了window,但是它的背景颜色是黑色,什么也没有出现,直到介绍完颜色才变!
  3. 最近,一个不使用 "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。使用信号来实现它。