我正在研究Unix 19.02和Qt 5.13.0。
我正在尝试在窗口中显示任何内容之前为我的应用程序进行介绍。所以,我想的是让QPainter在一段时间循环中改变背景颜色。我尝试了太多次,我在时间上遇到了问题:"我应该让qpainter开始介绍的时刻或事件是什么时候?我搜索并发现最好的办法是重新实现此功能:
void showEvent(QShowEvent* event) {...}
在该函数中,我调用"repaint((",它将完成所有介绍。 我尝试了所有这些方法:
- 在"paintEvent"函数中制作while循环。
- 在"paintEvent"函数之外进行while循环,每次我们更改背景的颜色时,我都称之为"repaint(("。当然,我为计算机做了一个小的超时,以减慢一点。 -注意:使用上面的这两种方式,窗口会显示,但它的背景色是黑色的,什么都没有显示,颜色也不会改变,直到介绍完成!
- 最后,一个不使用"QPainter"的while循环,它使用样式表代替,并且在我们更改"background-color"属性之后。我们称之为 :
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 秒 希望你理解我的情况。
您没有提供完整的代码,所以我在这里部分猜测。
在开始动画之前,需要等待主应用事件循环开始。 如果从QMainWindow
(或任何顶级QWidget
(构造函数调用该动画例程(末尾msleep()
(,则主窗口永远不会有机会显示自身(直到动画完成(。
如果我是对的,您可以考虑使用bool
标志从第一个QWidget::showEvent()
开始动画,以了解第一个节目何时发生。另一种方法是在构造函数中启动QTimer::singleShot(0, this, &MainWindow::animate)
(计时器将在主事件循环启动后触发(。 还有其他方法,但重点是您需要让 QApplication 事件循环运行并且窗口已经初始化。
说了这么多,我可能会采取不同的方法,也许使用QSplashScreen
或自定义QWidget在背景加载主窗口之前或同时显示动画。
此外,研究QString
模板/替换系统,特别是arg()
方法以及如何使用它们来简化字符串构造。
正如@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);
}
}
这是一个微不足道的情况。只需先显示欢迎窗口。关闭后,显示您的主窗口。使用信号来实现它。