在窗口中显示任何内容之前和窗口抛光后无法进行介绍

Posted

技术标签:

【中文标题】在窗口中显示任何内容之前和窗口抛光后无法进行介绍【英文标题】:unable to make an intro before showing anything in the window and after the window is polished 【发布时间】:2019-08-31 14:28:03 【问题描述】:

我正在开发 Unix 19.02 和 Qt 5.13.0。

我正在尝试在窗口中显示任何内容之前对我的应用程序进行介绍。所以,我的想法是让 QPainter 在一个循环中改变背景颜色。我尝试了太多次,我在时间上遇到了问题:“我应该让 qpainter 开始介绍的时刻或事件是什么时候?”。我搜索并发现最好的方法是重新实现此功能:

void showEvent(QShowEvent* event) ...  

在那个函数中,我调用“repaint()”,它会完成所有的介绍。 我尝试了所有这些方法:

    在“paintEvent”函数中创建while循环。 在“paintEvent”函数之外创建while循环,每次我们更改背景颜色时,我都会调用“repaint()”。当然,我为计算机设置了一个小超时以使其速度变慢一点。 -注意:使用上面这两种方式,窗口都会出现,但它的背景颜色是黑色的,没有任何显示,颜色也不会改变,直到介绍完成! 最后,一个不使用“QPainter”的while循环,它使用样式表代替,并且在我们更改“背景颜色”属性之后。我们致电:ui->centeralWidget->style->polish(ui->centeralWidget);

最后一种方式,强制窗口在介绍完全完成之前不显示(执行介绍需要 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(睡眠)* 50(代码将执行 50 次)= 5000 / 1000(单位为毫,因此除以 1000)= 5 秒 希望你了解我的情况。

【问题讨论】:

【参考方案1】:

你没有提供完整的代码,所以我在这里部分猜测。

在开始动画之前,您需要等待主应用事件循环开始。如果您从QMainWindow(或您的***QWidget)构造函数调用该动画例程(末尾带有msleep()),则主窗口永远不会有机会显示自己(直到动画完成)。

如果我是对的,您可以考虑使用 bool 标志从第一个 QWidget::showEvent() 开始您的动画,以了解第一个节目何时发生。另一种方法是在构造函数中启动QTimer::singleShot(0, this, &amp;MainWindow::animate)(一旦主事件循环开始,计时器将触发)。还有其他方法,但重点是需要让QApplication事件循环处于运行状态,并且窗口已经被初始化。

说了这么多,我可能会采取不同的方法,可能使用QSplashScreen 或自定义 QWidget 在后台加载主窗口之前或期间显示动画。

另外,查看QString 模板/替换系统,特别是arg() 方法以及如何使用它们来简化字符串构造。

【讨论】:

【参考方案2】:

正如@MaximPaperno 指出的那样,问题出在while-loop + msleep() 上,因为它们阻塞了事件循环,从而阻止了GUI 正常工作。对于这些情况,Qt提供了QTimer、QXAnimation等策略。这种情况下一个简单的解决方案就是使用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);
    

【讨论】:

【参考方案3】:

这是一个微不足道的情况。只需先显示欢迎窗口。当它关闭时,显示您的主窗口。使用信号来实现它。

【讨论】:

以上是关于在窗口中显示任何内容之前和窗口抛光后无法进行介绍的主要内容,如果未能解决你的问题,请参考以下文章

弹窗怎么设置

移动/调整窗口大小时闪烁

如何实现鼠标经过弹出窗口,鼠标离开后窗口消失? PS:重点是弹窗里面的内容还可以设置链接

无法使用 WinAPI 显示窗口

根据窗口大小改变悬浮窗显示方式并自动刷新页面

TERSUS画画一样开发软件 显示元件介绍-子页面及弹窗显示元件