PDA

View Full Version : Qt: animation to make a scene “enter” a window, update problem



sakya
18th July 2011, 09:11
Hi! :)

I'm trying to animate a scene to make it "enter" the window.
I want the scene to be located out of the window and then animate it to slide to enter the window.
I made a QMainWindow with no layout and only its CentralWidget.
My code works, but the problem is that the scene (or the view, or the window...) isn't updated while the animation is running so that I see just a slice of the scene while in movement (some automatic update?).
If I hide the window when the animation is finished and then show it the view is updated and all is ok.

I tried to updated/invalidate the view, the scene and the central widget but this doesn't solve my problem.

Can someone help me?

Here's my code:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPropertyAnimation>
#include <QParallelAnimationGroup>
#include <QPushButton>

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setFixedSize(800, 520);
m_Scene_1_Visible = false;

m_View_1 = NULL;
m_View_2 = NULL;
m_Scene_1 = NULL;
m_Scene_2 = NULL;

m_Btn = new QPushButton(ui->centralWidget);
m_Btn->setText(tr("Change"));
m_Btn->move(10, 490);
m_Btn->setFixedWidth(780);
connect(m_Btn, SIGNAL(clicked()), this, SLOT(changeScene()));
}

MainWindow::~MainWindow()
{
delete ui;
}

void MainWindow::changeScene()
{
m_Btn->setEnabled(false);
QParallelAnimationGroup* parallel = new QParallelAnimationGroup(this);

if (m_Scene_1_Visible){
m_Scene_2 = new QGraphicsScene(this);
m_Scene_2->setSceneRect(0, 0, 800, 480);
m_Scene_2->setItemIndexMethod(QGraphicsScene::NoIndex);
m_Scene_2->setBackgroundBrush(QPixmap("c:/Users/sakya/qtscenetest-build-desktop/debug/background_2.png"));

m_View_2 = new QGraphicsView(m_Scene_2, ui->centralWidget);
m_View_2->setRenderHint(QPainter::Antialiasing);
m_View_2->setCacheMode(QGraphicsView::CacheBackground);
m_View_2->setViewportUpdateMode(QGraphicsView::BoundingRectV iewportUpdate);
m_View_2->setFrameStyle(QFrame::NoFrame);
m_View_2->setFixedSize(800, 480);
m_View_2->move(QPoint(800, 0));
m_View_2->show();

QPropertyAnimation *ran = new QPropertyAnimation(m_View_1, "pos");
//ran->setEasingCurve(QEasingCurve::InOutCubic);
ran->setDuration(250);
ran->setStartValue(QPoint(0, m_View_1->pos().y()));
ran->setEndValue(QPoint(-m_View_1->size().width(), 0));
parallel->addAnimation(ran);

ran = new QPropertyAnimation(m_View_2, "pos");
//ran->setEasingCurve(QEasingCurve::InOutCubic);
ran->setDuration(250);
ran->setStartValue(QPoint(800, 0));
ran->setEndValue(QPoint(0, 0));
parallel->addAnimation(ran);
}else{
m_Scene_1 = new QGraphicsScene(this);
m_Scene_1->setSceneRect(0, 0, 800, 480);
m_Scene_1->setItemIndexMethod(QGraphicsScene::NoIndex);
m_Scene_1->setBackgroundBrush(QPixmap("c:/Users/sakya/qtscenetest-build-desktop/debug/background_1.png"));

m_View_1 = new QGraphicsView(m_Scene_1, ui->centralWidget);
m_View_1->setRenderHint(QPainter::Antialiasing);
m_View_1->setCacheMode(QGraphicsView::CacheBackground);
m_View_1->setViewportUpdateMode(QGraphicsView::BoundingRectV iewportUpdate);
m_View_1->setFrameStyle(QFrame::NoFrame);
m_View_1->setFixedSize(800, 480);
m_View_1->move(QPoint(800, 0));
m_View_1->show();

QPropertyAnimation *ran;
if (m_View_2 != NULL){
ran = new QPropertyAnimation(m_View_2, "pos");
//ran->setEasingCurve(QEasingCurve::InOutCubic);
ran->setDuration(250);
ran->setStartValue(QPoint(0, m_View_2->pos().y()));
ran->setEndValue(QPoint(-m_View_2->size().width(), 0));
parallel->addAnimation(ran);
}
ran = new QPropertyAnimation(m_View_1, "pos");
//ran->setEasingCurve(QEasingCurve::InOutCubic);
ran->setDuration(250);
ran->setStartValue(QPoint(800, 0));
ran->setEndValue(QPoint(0, 0));
parallel->addAnimation(ran);
}

connect(parallel, SIGNAL(finished()), this, SLOT(onAnimationFinished()));
parallel->start(QAbstractAnimation::DeleteWhenStopped);
}

void MainWindow::onAnimationFinished()
{
if (m_Scene_1_Visible){
delete m_Scene_1;
delete m_View_1;
}else{
delete m_Scene_2;
delete m_View_2;
}
m_Scene_1_Visible = !m_Scene_1_Visible;

m_Btn->setEnabled(true);
}

Many thanks. :)

sakya
20th July 2011, 08:27
I found a "solution" (there's probably a better one).
The problem is that the view isn't updated when its position is outside the window and it is not auto updated when animated to enter the window, invalidating the scene at every step of the animation solves this problem.

I subclassed QGraphicsView and invalidate the scene when the view is moved:

#ifndef MYVIEW_H
#define MYVIEW_H

#include <QGraphicsView>

class MyView : public QGraphicsView
{
Q_OBJECT
Q_PROPERTY(QPoint pos READ pos WRITE move DESIGNABLE false STORED false)

public:
MyView(QGraphicsScene *scene, QWidget *parent = 0);

QPoint pos();
void move(QPoint);
};

#endif // MYVIEW_H

#include "myview.h"

MyView::MyView(QGraphicsScene *scene, QWidget *parent) :
QGraphicsView(scene, parent)
{

}

QPoint MyView::pos()
{
return QGraphicsView::pos();
}

void MyView::move(QPoint pos)
{
QGraphicsView::move(pos);
if (scene())
scene()->invalidate(scene()->sceneRect());
}