Jacob
Jacob

Reputation: 333

QPropertyAnimation not running immediately when QAbstractAnimation::start() is called

I am trying to make a simple multi-page widget with QStackedWidgets in Qt Creator with Qt 4.8.6. The goal is to have a QLabel and QProgressBar fade away after the progress bar reaches full value. I thought the best way to achieve this was using QGraphicsOpacityEffect and QPropertyAnimation in tandem as seen below.

void MainWindow::AnimateStartScreen()
{
    //QSound::play("./Audio/THX-DeepNote-48Khz.wav");
    sleep(5);

    logoEffect = new QGraphicsOpacityEffect();
    logoAnimation = new QPropertyAnimation(logoEffect, "opacity");
    ui->startLogo->setGraphicsEffect(logoEffect);
    logoAnimation->setDuration(2000);
    logoAnimation->setStartValue(1);
    logoAnimation->setEndValue(0);
    logoAnimation->start();

    progressBarEffect = new QGraphicsOpacityEffect();
    progressBarAnimation = new QPropertyAnimation(progressBarEffect, "opacity");
    ui->startProgressBar->setGraphicsEffect(progressBarEffect);
    progressBarAnimation->setDuration(2000);
    progressBarAnimation->setStartValue(1);
    progressBarAnimation->setEndValue(0);
    progressBarAnimation->start();

    sleep(3);
}

Which is then called by the main method:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;

    w.HideTitleBar();
    w.CenterWidget();
    //QMainWindow::showFullScreen();
    w.show();
    w.IncrementProgressbar();
    w.AnimateStartScreen();
    w.ChangePageTo(1);

    return a.exec();
}

Here lies the problem. I want this animation to finish before I change the page like so:

void MainWindow::ChangePageTo(int page)
{
    ui->stackedWidget->setCurrentIndex(page);
}

Is there a way I can delay page change until my animation is complete? When I comment out the page change, the animation doesn't seem to even start until QApplication::exec() is called in my main method, evident by a 8 second waiting period (the combination of both sleep calls), rather than a 5 second delay before QAbstractAnimation::start() is called.

I believe what is happening is that the sleep(3) line is stopping the thread in which the GUI is running on, hence delaying the start of the animation for three seconds. When the sleep call has completed, I wonder if the animation tries to continue, but because of the page change,there is just no visible effect from the quick transition.

How can I make a 3 second delay without stopping the thread that the animation is running off of? Or are there any other suggestions that will produce the same effect?

Upvotes: 0

Views: 803

Answers (2)

Dmitry Sazonov
Dmitry Sazonov

Reputation: 8994

Use next pattern for non-blocking waiting (instead of sleep):

QEventLoop loop;
connect( progressBarAnimation, &QAbstractAnimaion::finished, &loop, &QEventLoop::quit );
loop.exec();

Upvotes: 1

G.M.
G.M.

Reputation: 12879

I believe what is happening is that the sleep(3) line is stopping the thread in which the GUI is running on

Almost certainly. For the animation to run you need to keep the message queue running which, in the code you've posted, won't occur until the subsequent call to a.exec().

If you really need to block execution of MainWindow::AnimateStartScreen until the animation has completed then perhaps a better idea would be to replace the call to sleep(3) with...

while (progressBarAnimation->state() != QAbstractAnimation::Stopped)
  QCoreApplication::processEvents();

(Although you might have to play about with the flags pass to QCoreApplication::processEvents to get the precise behaviour you require.)

Upvotes: 1

Related Questions