RazZziel
5th March 2012, 09:15
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:
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
newPage->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
ui->placeholder->addWidget(newPage);
newPage->setFocus();
connect(newPage,
SIGNAL(setPage(KioskPage*,KioskMainWindow::Directi on)),
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?
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:
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
newPage->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
ui->placeholder->addWidget(newPage);
newPage->setFocus();
connect(newPage,
SIGNAL(setPage(KioskPage*,KioskMainWindow::Directi on)),
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?