4.6がやってきた-Qt最新事情2010

第7回 ステートマシーンフレームワークの詳細[その3]

この記事を読むのに必要な時間:およそ 13 分

遷移とアニメーション効果

ステートマシンフレームワークAPIはアニメーションAPIに関連付けられていて,状態に設定されたプロパティの自動的なアニメーションをします。使い方はとても簡単で,遷移にプロパティアニメーションを設定するだけです。以降のサンプルコード(リスト8)を実行すると,次の動画のようになります。

動画1 遷移へのアニメーションづけ

リスト8

 1: #include <QApplication>
 2: #include <QStateMachine>
 3: #include <QSignalTransition>
 4: #include <QPropertyAnimation>
 5: #include <QPushButton>
 6: #include <QLayout>
 7: 
 8: int main( int argc, char** argv )
 9: {
10:     QApplication app( argc, argv );
11: 
12:     QWidget* drawWidget = new QWidget;
13:     drawWidget->setFixedSize( 400, 200 );
14: 
15:     QWidget* leftWidget = new QWidget( drawWidget );
16:     QPalette palette = leftWidget->palette();
17:     palette.setColor( QPalette::Window, Qt::green );
18:     leftWidget->setPalette( palette );
19:     leftWidget->setAutoFillBackground( true );
20:     leftWidget->setGeometry( 90, 90, 20, 20 );
21: 
22:     QWidget* rightWidget = new QWidget( drawWidget );
23:     palette = leftWidget->palette();
24:     palette.setColor( QPalette::Window, Qt::red );
25:     rightWidget->setPalette( palette );
26:     rightWidget->setAutoFillBackground( true );
27:     rightWidget->setGeometry( 290, 90, 20, 20 );
28: 

drawWidgetの上に,緑色のleftWidgetと赤色のrightWidgetを置いています。置いた両ウィジェットは,大きさを変えたいのでレイアウトマネージャには管理させません。

29:     QPushButton* leftAnimateButton = new QPushButton( "Animate" );
30:     QPushButton* rightAnimateButton = new QPushButton( "Animate" );
31: 
32:     QHBoxLayout* buttonLayout = new QHBoxLayout;
33:     buttonLayout->addStretch();
34:     buttonLayout->addWidget( leftAnimateButton );
35:     buttonLayout->addStretch();
36:     buttonLayout->addWidget( rightAnimateButton );
37:     buttonLayout->addStretch();
38: 
39:     QVBoxLayout* topLayout = new QVBoxLayout;
40:     topLayout->addWidget( drawWidget );
41:     topLayout->addLayout( buttonLayout );
42: 

操作用のボタンを作り,全体をレイアウトしています。

43:     QWidget topWidget;
44:     topWidget.setLayout( topLayout );
45: 
46:     QStateMachine* stateMachine = new QStateMachine( &topWidget );
47:     
48:     QState* parallelState = new QState(QState::ParallelStates, stateMachine );
49:     QState* leftStateGroup = new QState( parallelState );
50:     QState* rightStateGroup = new QState( parallelState );
51: 

緑と赤の両ウィジェットを並行して操作するために並列状態を使っています。

52:     QState* leftWidgetStateSmall = new QState( leftStateGroup );
53:     QState* leftWidgetStateLarge = new QState( leftStateGroup );
54:     leftWidgetStateSmall->assignProperty( leftWidget, "geometry", QRectF( 90, 90, 20, 20 ) );
55:     leftWidgetStateLarge->assignProperty( leftWidget, "geometry", QRectF( 10, 10, 180, 180 ) );
56:     leftStateGroup->setInitialState( leftWidgetStateSmall );
57: 

小さいときの状態と大きいときの状態を用意し,geometry プロパティでそれぞれの状態での大きさを設定しています。

58:     QSignalTransition* leftMaximizeTransition = leftWidgetStateSmall->addTransition( leftAnimateButton, SIGNAL(clicked()), leftWidgetStateLarge );
59:     QPropertyAnimation* animation = new QPropertyAnimation( leftWidget, "geometry" );
60:     animation->setDuration( 4 * 1000 );
61:     leftMaximizeTransition->addAnimation( animation );
62:     QSignalTransition* leftMinimizeTransition = leftWidgetStateLarge->addTransition( leftAnimateButton, SIGNAL(clicked()), leftWidgetStateSmall );
63:     animation = new QPropertyAnimation( leftWidget, "geometry" );
64:     animation->setDuration( 4 * 1000 );
65:     leftMinimizeTransition->addAnimation( animation );
66: 

ボタンをクリックすると緑のウィジェットが大きくなったり小さくなったりするようなアニメーションを作成し,QSignalTransition::addAnimation()で設定するだけで,遷移が起きるとアニメーションが行われます。

67:     QState* rightWidgetStateSmall = new QState( rightStateGroup );
68:     QState* rightWidgetStateLarge = new QState( rightStateGroup );
69:     rightWidgetStateSmall->assignProperty( rightWidget, "geometry", QRectF( 90 + 200, 90, 20, 20 ) );
70:     rightWidgetStateLarge->assignProperty( rightWidget, "geometry", QRectF( 10 + 200, 10, 180, 180 ) );
71:     rightStateGroup->setInitialState( rightWidgetStateSmall );
72: 
73:     QSignalTransition* rightMaximizeTransition = rightWidgetStateSmall->addTransition( rightAnimateButton, SIGNAL(clicked()), rightWidgetStateLarge );
74:     animation = new QPropertyAnimation( rightWidget, "geometry" );
75:     animation->setDuration( 4 * 1000 );
76: 
77:     rightMaximizeTransition->addAnimation( animation );
78:     QSignalTransition* rightMinimizeTransition = rightWidgetStateLarge->addTransition( rightAnimateButton, SIGNAL(clicked()), rightWidgetStateSmall );
79:     animation = new QPropertyAnimation( rightWidget, "geometry" );
80:     animation->setDuration( 4 * 1000 );
81:     rightMinimizeTransition->addAnimation( animation );
82: 

右の赤いウィジェットについて,緑のウィジェットと同様にアニメーションをするようにしています。

83:     stateMachine->setInitialState( parallelState );
84:     stateMachine->start();
85: 
86:     topWidget.show();
87: 
88:     return app.exec();
89: }

おわりに

次回は,この連載の最終回でイフェクトについて説明します。そして,しばらく期間を置いて,Qt 4.7リリース時にその概要と,この連載で説明した機能をベースにした宣言的ユーザインターフェースQt Quickの連載を予定しています。

著者プロフィール

杉田研治(すぎたけんじ)

1955年生まれ。東京都出身。株式会社SRAに勤務。プログラマ。

仕事のほとんどをMac OS XとKubuntu KDE 4でQtと供に過ごす。