Avoid flicker during slideshow with QPropertyAnimation
I hace a fullscreen program with several screens, and I want to go for one screen to the next one witht an slideshow animation.
I have a fullscreeen QMainWidget, with a placeholder VerticalLayout, where I put different QWidgets that act as "screens" for my application, one at a time. The user interacts with the current screen, and when it's time to go to the next one, I remove the current page from the vertical layout and place the new page instead.
It works flawlessly, but I want to spice it up with some QPropertyAnimation. I want to transition from one page to the next one with a little slideshow animation. I'm using the "geometry" property, to move both the old page and the new page, right-to-left. This is my code:
Code:
if (m_currentPage && animate)
{
// Don't allow the user to interact with the old page as it's being carried away
m_currentPage->setEnabled(false);
QRect a
= ui
->placeholder
->geometry
();
QRect b
= QRect(a.
width(), a.
y(), a.
width(), a.
height());
QRect c
= QRect(-a.
width(), a.
y(), a.
width(), a.
height());
int animationDuration = 400;
QPropertyAnimation *animation = new QPropertyAnimation(m_currentPage, "geometry", this);
animation->setStartValue(a);
animation->setEndValue(direction == Forward ? c : b);
animation->setDuration(animationDuration);
animation->setEasingCurve(QEasingCurve::OutQuad);
animation->start();
connect(animation, SIGNAL(finished()), m_currentPage, SLOT(deleteLater()));
QPropertyAnimation *animation2 = new QPropertyAnimation(newPage, "geometry", this);
animation2->setStartValue(direction == Forward ? b : c);
animation2->setEndValue(a);
animation2->setDuration(animationDuration);
animation2->setEasingCurve(QEasingCurve::OutQuad);
animation2->start();
connect(animation2, SIGNAL(finished()), newPage, SLOT(setFocus()));
}
else
{
// Remove previous page
clearLayout(ui->placeholder);
}
// Set new page
ui->placeholder->addWidget(newPage);
newPage->setFocus();
connect(newPage,
SIGNAL(setPage(KioskPage*,KioskMainWindow::Direction)),
SLOT(setPage(KioskPage*,KioskMainWindow::Direction)));
newPage->init();
m_currentPage = newPage;
languageChange();
if (animate)
{
newPage->hide();
QTimer::singleShot(100, newPage,
SLOT(show
()));
}
It works fairly well, but has one annoying bug: after this code is run, the function quits, the control returns to Qt internals and windows start to be drawn, what I see is, first, the newPage flickers once all over the m_currentPage, just for a fraction of a second, and then it disappears and the animation starts smoothly. I've tried a lot of stuff here, and that ugly QTimer::singleShot(100, newPage, SLOT(show())); is the only thing that appears to at least disguise part of the problem, but not completely. As soon as the show() slot is called, newPage flickers once over m_currentPage, disappears and appears again where it should be according to the QPropertyAnimation.
Does anyone know why this is happening, and what I could do to avoid it?
Re: Avoid flicker during slideshow with QPropertyAnimation
Please provide a minimal compilable example reproducing the problem.
1 Attachment(s)
Re: Avoid flicker during slideshow with QPropertyAnimation
Re: Avoid flicker during slideshow with QPropertyAnimation
In my opinion the problem is with your "placeholder" layout. If you want to animate a page, it can't be part of a layout.
Code:
#include <QtGui>
Q_OBJECT
public:
l->addWidget(placeholder);
l->addWidget(b);
b->setText("click");
connect(b, SIGNAL(clicked()), this, SLOT(nextPage()));
current = 0;
}
public slots:
void nextPage() {
newPage->setAutoFillBackground(true);
newPage->setPalette(p);
newPage->setParent(placeholder);
QPropertyAnimation *anim = new QPropertyAnimation(newPage, "geometry", newPage);
QRect start
= placeholder
->rect
();
start.setTopLeft(start.topRight());
newPage->setGeometry(start);
anim->setStartValue(start);
anim->setEndValue(placeholder->rect());
anim->start();
if(current) {
QPropertyAnimation *anim = new QPropertyAnimation(current, "geometry", current);
anim->setStartValue(placeholder->rect());
QRect r
= placeholder
->rect
();
r.translate(-r.width(), 0);
anim->setEndValue(r);
connect(anim, SIGNAL(finished()), current, SLOT(deleteLater()));
anim->start();
}
current = newPage;
current->show();
}
private:
};
#include "main.moc"
int main(int argc, char **argv) {
Widget w;
w.show();
return app.exec();
}
Re: Avoid flicker during slideshow with QPropertyAnimation
This pitiful mortal shall bow before you, oh wise Master Of Zen.