グラフィックスビューのアイテムのアニメーション
グラフィックスビューのQGraphicsItemアイテムにアニメーションフレームワークを適用するには、
- 1.QGraphicsObjectをサブクラス化して、
アイテムを作成する。 - 2.QObjectとQGraphicsRectItemやQGraphicsPixmapItemを多重継承したアイテムを作成する。
QGraphicsSvgItem、
ここでは、
今回紹介するアニメーションプログラムのソースリストはこちらからダウンロードしてください。
examples.zip
1: #include <QApplication>
2: #include <QGraphicsView>
3: #include <QGraphicsScene>
4: #include <QGraphicsPixmapItem>
5: #include <QPropertyAnimation>
6: #include <QLayout>
7: #include <<QPushButton>
8:
9: class MovableGraphicsPixmapItem : public QObject, public QGraphicsPixmapItem
10: {
11: Q_OBJECT
12: Q_PROPERTY( QPointF pos READ pos WRITE setPos )
13:
14: public:
15: MovableGraphicsPixmapItem( const QPixmap& pixmap, QGraphicsItem* parent = 0 )
16: : QObject(), QGraphicsPixmapItem( pixmap, parent ) {
17: }
18: };
19:
2番目の方法を用いた、
20: class HarnessPrivate
21: {
22: public:
23: HarnessPrivate()
24: : movingAreaSize( QSize( 360, 120 ) ), horizontalOffset( 8 ) {
25: }
26:
27: QSize movingAreaSize;
28: int horizontalOffset;
29: QPropertyAnimation* yellowBallAnimation;
30: };
31:
32: class Harness : public QWidget
33: {
34: Q_OBJECT
35: Q_DECLARE_PRIVATE( Harness )
36:
37: public:
38: Harness();
39: ~Harness();
40:
41: private slots:
42: void startAnimation();
43:
44: private:
45: MovableGraphicsPixmapItem* createBallItem( const QString& pixmapFileName );
46: HarnessPrivate* d_ptr;
47: };
48:
動くアイテムがあるグラフィックスビューを置くためのクラスです。今迄のサンプルプログラムと同じように、
49: Harness::Harness()
50: : QWidget( 0 ), d_ptr( new HarnessPrivate )
51: {
52: Q_D( Harness );
53:
54: QGraphicsScene* graphicsScene = new QGraphicsScene( 0, 0, d->>movingAreaSize.width(), d->movingAreaSize.height() );
55: MovableGraphicsPixmapItem* yellowBallItem = createBallItem( ":/images/YellowGlassBall.png" );
56: QSize ballSize = yellowBallItem->pixmap().size();
57: int ballSpacingY = ( d->movingAreaSize.height() - ballSize.height()) / 2;
58: int yellowBallY = ballSpacingY;
59: yellowBallItem->setPos( d->horizontalOffset, yellowBallY );
60: graphicsScene->addItem( yellowBallItem );
61:
グラフィックスシーンの左端に、
62: QGraphicsView* graphicsView = new QGraphicsView();
63: graphicsView->setScene( graphicsScene );
64:
65: QPushButton* animateButton = new QPushButton( "Animate" );
66:
67: QHBoxLayout* buttonLayout = new QHBoxLayout;
68: buttonLayout->addStretch();
69: buttonLayout->addWidget( animateButton );
70:
71: QVBoxLayout* topLayout = new QVBoxLayout;
72: topLayout->addWidget( graphicsView );
73: topLayout->addLayout( buttonLayout );
74:
75: setLayout( topLayout );
76: setFixedSize( sizeHint() );
77:
78: d->yellowBallAnimation = new QPropertyAnimation( yellowBallItem, "pos", this );
79: d->yellowBallAnimation->setDuration( 5 * 1000 );
80: int movableBallStartX = d->horizontalOffset;
81: int movableBallEndX = d->movingAreaSize.width() - ballSize.width() - d->horizontalOffset;
82: d->yellowBallAnimation->setStartValue( QPoint( movableBallStartX, yellowBallY ) );
83: d->yellowBallAnimation->setEndValue( QPoint( movableBallEndX, yellowBallY ) );
84: d->yellowBallAnimation->setEasingCurve( QEasingCurve::OutBounce );
85:
posプロパティを使ってアニメーションするのは、
86: connect( animateButton, SIGNAL( clicked() ), SLOT( startAnimation() ) );
87: }
88:
89: Harness::~Harness()
90: {
91: delete d_ptr;
92: }
93:
94: void Harness::startAnimation()
95: {
96: Q_D( Harness );
97:
98: d->yellowBallAnimation->start();
99: }
100:
101: MovableGraphicsPixmapItem* Harness::createBallItem( const QString& pixmapFileName )
102: {
103: MovableGraphicsPixmapItem* item = new MovableGraphicsPixmapItem( QPixmap( pixmapFileName ) );
104:
105: return item;
106: }
107:
108: int main( int argc, char** argv )
109: {
110: QApplication app( argc, argv );
111:
112: Harness harness;
113: harness.show();
114:
115: return app.exec();
116: }
117:
118: #include "movablegraphicsitem.moc"
リスト1のサンプルプログラムを実行すると、
複数のアニメーションの扱い方
アニメーションフレームワークには、
シーケンシャルアニメーションによるアニメーションの順次実行
図1のように、

コードの変更箇所はリスト2のようになります。
1: #include <QApplication>
2: #include <QGraphicsView>
3: #include <QGraphicsScene>
4: #include <QGraphicsPixmapItem>
5: #include <QPropertyAnimation>
6: #include <QSequentialAnimationGroup>
7: #include <QLayout>
8: #include <QPushButton>
9:
QSequentialAnimationGroup クラスを使うため、
21: class HarnessPrivate
22: {
23: public:
24: HarnessPrivate()
25: : movingAreaSize( QSize( 360, 320 ) ), horizontalOffset( 8 ) {
26: }
27:
28: QSize movingAreaSize;
29: int horizontalOffset;
30: QSequentialAnimationGroup* ballAnimationGroup;
31: };
32:
30行目で、
33: class Harness : public QWidget
34: {
35: Q_OBJECT
36: Q_DECLARE_PRIVATE( Harness )
37:
38: public:
39: Harness();
40: ~Harness();
41:
42: private slots:
43: void startAnimation();
44:
45: private:
46: MovableGraphicsPixmapItem* createBallItem( const QString& pixmapFileName );
47: QPropertyAnimation* createBallAnimation( MovableGraphicsPixmapItem* item, int duration, int startX, int endX, int y );
48: HarnessPrivate* d_ptr;
49: };
50:
黄、
51: Harness::Harness()
52: : QWidget( 0 ), d_ptr( new HarnessPrivate )
53: {
54: Q_D( Harness );
55:
56: QGraphicsScene* graphicsScene = new QGraphicsScene( 0, 0, d->movingAreaSize.width(), d->movingAreaSize.height() );
57: MovableGraphicsPixmapItem* yellowBallItem = createBallItem( ":/images/YellowGlassBall.png" );
58: QSize ballSize = yellowBallItem->pixmap().size();
59: int ballSpacingY = ( d->movingAreaSize.height() - ballSize.height() * 3 ) / 4;
3つのボールがあるので、
60: int yellowBallY = ballSpacingY;
61: yellowBallItem->setPos( d->horizontalOffset, yellowBallY );
62: graphicsScene->addItem( yellowBallItem );
63:
64: MovableGraphicsPixmapItem* greenBallItem = createBallItem( ":/images/GreenGlassBall.png" );
65: int greenBallY = yellowBallY + ballSize.height() + ballSpacingY;
66: greenBallItem->setPos( d->horizontalOffset, greenBallY );
67: graphicsScene->addItem( greenBallItem );
68:
69: MovableGraphicsPixmapItem* redBallItem = createBallItem( ":/images/RedGlassBall.png" );
70: int redBallY = greenBallY + ballSize.height() + ballSpacingY;
71: redBallItem->setPos( d->horizontalOffset, redBallY );
72: graphicsScene->addItem( redBallItem );
64~72行目で緑と赤のボールを追加しています。
90: int movableBallStartX = d->horizontalOffset;
91: int movableBallEndX = d->movingAreaSize.width() - ballSize.width() - d->horizontalOffset;
92:
93: QPropertyAnimation* yellowBallAnimation = createBallAnimation( yellowBallItem, 5 * 1000, movableBallStartX, movableBallEndX, yellowBallY );
94: QPropertyAnimation* greenBallAnimation = createBallAnimation( greenBallItem, 5 * 1000, movableBallStartX, movableBallEndX, greenBallY );
95: QPropertyAnimation* redBallAnimation = createBallAnimation( redBallItem, 5 * 1000, movableBallStartX, movableBallEndX, redBallY );
96:
97: d->ballAnimationGroup = new QSequentialAnimationGroup( this );
98: d->ballAnimationGroup->addAnimation( yellowBallAnimation );
99: d->ballAnimationGroup->addAnimation( greenBallAnimation );
100: d->ballAnimationGroup->addAnimation( redBallAnimation );
101:
102: connect( animateButton, SIGNAL( clicked() ), SLOT( startAnimation() ) );
103: }
93~100行目では各ボールを5秒ずつ動かすアニメーションを作り、
110: void Harness::startAnimation()
111: {
112: Q_D( Harness );
113:
114: foreach ( QPropertyAnimation* propertyAnimation, findChildren<QPropertyAnimation*>() ) {
115: MovableGraphicsPixmapItem* item = ( MovableGraphicsPixmapItem* )propertyAnimation->targetObject();
116: item->setProperty( "pos", propertyAnimation->startValue() );
117: }
118:
119: d->ballAnimationGroup->start();
120: }
114~116行目で、
119行目でアニメーショングループのstart()を呼んで、
129: QPropertyAnimation* Harness::createBallAnimation( MovableGraphicsPixmapItem* item, int duration, int startX, int endX, int y )
130: {
131: QPropertyAnimation* ballAnimation = new QPropertyAnimation( item, "pos", this );
132: ballAnimation->setDuration( duration );
133: ballAnimation->setStartValue( QPoint( startX, y ) );
134: ballAnimation->setEndValue( QPoint( endX, y ) );
135: ballAnimation->setEasingCurve( QEasingCurve::OutBounce );
136:
137: return ballAnimation;
138: }
各ボールのアニメーションを生成するための補助メソッドです。このプログラムを実行すると、
パラレルアニメーションによるアニメーションの並行実行
今度は、

1: #include <QApplication>
2: #include <QGraphicsView>
3: #include <QGraphicsScene>
4: #include <QGraphicsPixmapItem>
5: #include <QPropertyAnimation>
6: #include <QSequentialAnimationGroup>
7: #include <QParallelAnimationGroup>
8: #include <QLayout>
9: #include <QPushButton>
QParallelAnimationGroupクラスを使うために、
22: class HarnessPrivate
23: {
24: public:
25: HarnessPrivate()
26: : movingAreaSize( QSize( 360, 320 ) ), horizontalOffset( 8 ) {
27: }
28:
29: QSize movingAreaSize;
30: int horizontalOffset;
31: QParallelAnimationGroup* ballAnimationGroup;
32: };
33:
ballAnimationGroupをQParallelAnimationGroupに変更します。
91: int movableBallStartX = d->horizontalOffset;
92: int movableBallEndX = d->movingAreaSize.width() - ballSize.width() - d->horizontalOffset;
93:
94: QPropertyAnimation* yellowBallAnimation = createBallAnimation( yellowBallItem, 20 * 1000, movableBallStartX, movableBallEndX, yellowBallY );
95: QPropertyAnimation* greenBallAnimation = createBallAnimation( greenBallItem, 10 * 1000, movableBallStartX, movableBallEndX, greenBallY );
96: QPropertyAnimation* redBallAnimation = createBallAnimation( redBallItem, 10 * 1000, movableBallStartX, movableBallEndX, redBallY );
97:
98: d->ballAnimationGroup = new QParallelAnimationGroup( this );
99: d->ballAnimationGroup->addAnimation( yellowBallAnimation );
100: QSequentialAnimationGroup* sequentialAnimation = new QSequentialAnimationGroup( this );
101: sequentialAnimation->addAnimation( greenBallAnimation );
102: sequentialAnimation->addAnimation( redBallAnimation );
103: d->ballAnimationGroup->addAnimation( sequentialAnimation );
104:
105: connect( animateButton, SIGNAL( clicked() ), SLOT( startAnimation() ) );
106: }
94~96行目では黄色のボールのアニメーション時間を20秒にし、
98行目でQParallelAnimationGroupのインスタンスを生成し、
このプログラムを実行すると、
おわりに
Qtのオブジェクトのプロパティのアニメーションが、