【QML】Item.transitions以外の選択肢:状態遷移アニメーションの代替方法

2025-06-06

Item.transitionsは、QML(Qt Meta-Object Language)において、UI要素(Item)の状態変化に伴うアニメーションを定義するためのプロパティです。

QMLでは、UI要素は複数の「状態」(State)を持つことができます。例えば、ボタンには「通常の状態」「ホバー状態」「押されている状態」などがあり、ウィンドウには「最大化された状態」「最小化された状態」などがあります。

Item.transitionsプロパティは、ある状態から別の状態へUI要素が移行する際に、どのようなアニメーション(例えば、位置の変更、サイズの変更、色の変更など)を適用するかを指定するために使用されます。これにより、ユーザーインターフェースに滑らかで視覚的に魅力的な変化をもたらすことができます。

主な特徴と使い方

  1. Transition 要素: Item.transitionsプロパティには、1つまたは複数のTransition要素をリストとして含めます。各Transition要素が特定の状態遷移に対するアニメーションを定義します。

    Item {
        // ...
        states: [
            // 状態の定義
        ]
    
        transitions: [
            Transition {
                // アニメーションの定義
            }
        ]
        // ...
    }
    
  2. fromto プロパティ: Transition要素内で、どの状態から (from) どの状態へ (to) 移行する際にこのアニメーションを適用するかを指定できます。

    • from: "*": 任意の状態から。
    • to: "*": 任意の状態へ。
    • 特定の状態名を指定することもできます(例: from: "normal", to: "pressed")。
  3. アニメーションの定義: Transition要素の内部には、実際に実行するアニメーションを定義するアニメーション要素(例: PropertyAnimation, NumberAnimation, ColorAnimation, SequentialAnimation, ParallelAnimation など)を配置します。

    Transition {
        from: "normal"
        to: "highlighted"
        PropertyAnimation {
            target: rect // アニメーションの対象となるオブジェクト
            properties: "color,width" // アニメーションさせるプロパティ
            duration: 200 // アニメーションの時間(ミリ秒)
        }
    }
    
  4. reversible プロパティ: Transitionが双方向(fromからtoへ、そしてtoからfromへ)で適用されるべきかを指定します。trueに設定すると、fromからtoへのアニメーションと、toからfromへのアニメーションの両方が自動的に定義されます。

以下は、Rectangleの色とサイズが状態に応じて変化する簡単な例です。

import QtQuick 2.15
import QtQuick.Window 2.15

Window {
    width: 400
    height: 300
    visible: true
    title: "Item.transitions Example"

    Rectangle {
        id: myRect
        width: 100
        height: 100
        color: "red"
        x: 50
        y: 50

        // 状態の定義
        states: [
            State {
                name: "expanded" // 状態名
                PropertyChanges {
                    target: myRect
                    width: 200
                    height: 200
                    color: "blue"
                    x: 100
                    y: 100
                }
            },
            State {
                name: "contracted" // 別の状態名
                PropertyChanges {
                    target: myRect
                    width: 50
                    height: 50
                    color: "green"
                    x: 200
                    y: 200
                }
            }
        ]

        // 状態遷移時のアニメーション定義
        transitions: [
            Transition {
                from: "*" // 任意の状態から
                to: "*"   // 任意の状態へ
                // 並行して実行されるアニメーション
                ParallelAnimation {
                    NumberAnimation {
                        properties: "width,height,x,y" // 複数のプロパティをアニメーション
                        duration: 500 // 0.5秒
                        easing.type: Easing.OutCubic // イージング関数
                    }
                    ColorAnimation {
                        property: "color" // 色をアニメーション
                        duration: 500
                    }
                }
            }
        ]

        // クリックで状態を切り替える
        MouseArea {
            anchors.fill: parent
            onClicked: {
                if (myRect.state === "") { // 初期状態から
                    myRect.state = "expanded";
                } else if (myRect.state === "expanded") {
                    myRect.state = "contracted";
                } else {
                    myRect.state = ""; // 初期状態に戻す
                }
            }
        }
    }
}

この例では、myRectをクリックすると、その状態がexpandedcontracted、そして初期状態へと切り替わります。その際、transitionsで定義されたParallelAnimationによって、サイズ、位置、色が滑らかに変化します。



Item.transitionsはQMLで状態遷移のアニメーションを定義するための強力な機能ですが、設定ミスや予期しない動作により問題が発生することがあります。ここでは、よくあるエラーとその解決策を説明します。

アニメーションが全く再生されない、または瞬時に切り替わる

最もよくある問題の一つです。

原因

  • バインディングが壊れている
    QMLのプロパティバインディングは強力ですが、JavaScriptによる直接的な代入によって壊れることがあります。プロパティがバインディングされている場合、そのプロパティに直接値を代入すると、そのバインディングが解除され、アニメーションが適用されなくなることがあります。
  • from と to の状態が正しくない
    Transitionfromまたはtoプロパティに指定された状態名が、実際に変更される状態名と一致していない。特に、デフォルトの状態から遷移する場合、from: ""またはfrom: "*"を使用する必要があります。
  • target プロパティの指定ミス
    アニメーションの対象となるItemidが正しくtargetに指定されていない。
  • properties プロパティの指定ミス
    PropertyAnimationなどで、アニメーションさせるプロパティが正しく指定されていない(例: "x"とすべきところを"X"と書いている、複数のプロパティをカンマ区切りで指定していない)。
  • アニメーションの定義が不足している
    Transition要素内に実際のアニメーション(例: PropertyAnimationNumberAnimationなど)が定義されていないか、定義されているプロパティが変更されるべきプロパティと一致していない。

トラブルシューティング

  • 状態変更を引き起こすコード(例: MouseArea.onClickedハンドラ)で、アニメーションさせたいプロパティに直接値を代入している場合、それが原因でバインディングが壊れていないか確認してください。理想的には、状態を変更するだけで、QMLエンジンがTransitionを介してプロパティの変化をアニメーションするようにすべきです。
  • Transitionfromtoプロパティを注意深く確認し、意図した状態遷移にアニメーションが適用されるように設定されているか確認してください。最初はfrom: "*"to: "*"で広範囲に適用してみて、動作を確認してから絞り込むのが良い方法です。
  • targetプロパティがアニメーションさせたいItemidを指しているか確認してください。
  • PropertyAnimationpropertiesプロパティが、変更されるべきプロパティの名前と完全に一致しているか(大文字小文字も含む)確認してください。複数のプロパティをアニメーションする場合は、"width,height"のようにカンマで区切ります。
  • Transition内にPropertyAnimationなどのアニメーション要素が正しく含まれているか確認してください。

アニメーションが一方通行で、逆方向の遷移で再生されない

原因

  • reversible プロパティの欠如または誤解
    Transitionreversibleプロパティがfalse(デフォルト)の場合、fromからtoへの遷移にのみアニメーションが適用され、toからfromへの逆遷移には適用されません。

トラブルシューティング

  • ただし、ParallelAnimationを使っている場合や、fromtoがワイルドカード(*)でない場合は、reversible: trueを設定するだけではうまくいかないことがあります。その場合は、逆方向の遷移 (from: "toState", to: "fromState") に対する別のTransitionを明示的に定義することを検討してください。
  • 逆方向の遷移でもアニメーションさせたい場合は、Transitionreversible: trueを追加します。

複数のTransitionが競合する、または意図しないTransitionが適用される

原因

  • 複数のTransitionが同じ状態遷移にマッチしてしまう場合、Qt QMLは「最も具体的な」Transitionを選択します。しかし、開発者の意図と異なるTransitionが選択されることがあります。

トラブルシューティング

  • 特定のTransitionを一時的に無効にしたい場合は、enabled: falseプロパティを使用できます。
  • Transitionの定義順序も影響を与える可能性があります。Qt QMLは通常、最初にマッチしたものを優先しますが、より具体的なものが優先されるルールがあるため、複雑な場合は注意が必要です。
  • fromtoプロパティをできるだけ具体的に指定し、あいまいさを減らします。

Repeater内の要素でTransitionが機能しない

Repeaterで動的に生成された要素のTransitionが期待通りに動作しないことがあります。

原因

  • Repeater内の要素が固有のidを持たないため、Transitiontarget指定が難しい。
  • Repeatermodelが変更された際に、要素が完全に再作成される場合、アニメーションが適用される前に要素が消えたり現れたりしてしまうことがあります。

トラブルシューティング

  • 特定のプロパティ変更にアニメーションを適用したい場合は、Behavior on <property>を使用する方が簡単な場合があります。
  • Repeaterで要素の追加/削除/移動のアニメーションを行う場合は、ListViewGridViewなどのビューアイテムのaddremovepopulateなどの専用のTransitionを使用することを検討してください。これらはモデルの変更をより適切に処理するように設計されています。

パフォーマンスの問題(アニメーションがカクつく)

原因

  • レイアウトの再計算
    アニメーションによってレイアウトが頻繁に再計算される場合、パフォーマンスに影響が出ます。
  • UIスレッドのブロック
    QMLは通常、メイン(UI)スレッドで動作します。重いJavaScript処理やC++からの同期的な呼び出しがUIスレッドをブロックすると、アニメーションが中断されたり、カクついたりします。
  • 複雑なアニメーションや多数の要素
    多数の要素を同時にアニメーションしたり、複雑な計算を伴うアニメーション(シェーダーなど)を使用したりすると、パフォーマンスが低下し、アニメーションがカクつくことがあります。

トラブルシューティング

  • LoaderやComponent.onCompletedで遅延ロードを行う
    必要になるまでUI要素の作成を遅らせることで、初期ロード時のパフォーマンスを向上させます。
  • ワーカー(WorkerScriptやC++のスレッド)を使用する
    UIスレッドをブロックする可能性のある重い処理は、別のスレッドで行うようにします。
  • Layer.enabledを使用する
    複雑なアニメーションの場合、アニメーション中のアイテムをレイヤーとしてキャッシュすることで、描画パフォーマンスを向上させることができます(ただし、メモリ使用量は増えます)。
  • opacityではなくvisibleをアニメーションしようとしている
    visibleプロパティはブール値なので直接アニメーションできません。フェードイン/アウトのような効果はopacityをアニメーションさせることで実現します。opacityを0にした後にvisible: falseに設定する、といった工夫が必要です。
  • アニメーションを簡素化する
    必要以上に多くのプロパティをアニメーションしたり、複雑なイージングカーブを使いすぎたりしていないか確認してください。
  • プロファイリングツールを使用する
    Qt CreatorにはQMLプロファイラが内蔵されており、どこで時間がかかっているかを特定するのに非常に役立ちます。これを活用してボトルネックを特定してください。

アニメーションが期待通りに開始しない、または終了しない

原因

  • 外部からのプロパティ変更
    Transitionが定義されているアイテムのプロパティが、JavaScriptやC++から直接変更された場合、Transitionがトリガーされないことがあります。
  • StateのPropertyChangesとTransitionの競合
    State内のPropertyChangesTransitionのアニメーションと競合し、アニメーションが期待通りに再生されないことがあります。Transitionは、PropertyChangesによって引き起こされるプロパティの変化をアニメーションするために使用されるため、通常は問題ありませんが、特定の複雑なシナリオでは注意が必要です。
  • 複雑なアニメーションシーケンスでは、SequentialAnimationParallelAnimationを適切に利用することで、アニメーションの順序や同時実行性を制御できます。
  • プロパティ変更が意図した状態遷移によってのみ行われているか確認してください。
  • StateTransitionの関係を明確に理解する:Stateはプロパティの「最終的な値」を定義し、Transitionはその値への「移行方法」を定義します。

デバッグのヒント

  • QML Profilerを使う
    パフォーマンスの問題を特定するために、QML Profilerを使ってフレームレート、CPU使用率、レンダリング時間などを分析します。
  • QML Debuggerを使う
    Qt CreatorのQML Debuggerは、プロパティの値の監視、ブレークポイントの設定、JavaScriptコードのステップ実行など、デバッグに非常に役立ちます。
  • console.log()を多用する
    状態がいつ変更され、どのTransitionが実行されているか、アニメーションのrunningプロパティがどうなっているかなどをconsole.log()で出力し、動作を追跡します。


Item.transitionsはQMLにおいて、UI要素の状態変化に伴うアニメーションを定義するために使用されます。ここでは、いくつかの具体的なコード例を挙げて説明します。

例1:基本的な状態遷移と単一プロパティのアニメーション

最も基本的な例です。Rectangleの色とサイズがクリックによって変化し、その変化がアニメーションされます。

import QtQuick 2.15
import QtQuick.Window 2.15

Window {
    width: 400
    height: 300
    visible: true
    title: "Basic Transition Example"

    Rectangle {
        id: myRect
        width: 100
        height: 100
        color: "red"
        x: 50
        y: 50

        // 状態の定義
        states: [
            State {
                name: "expanded" // 状態名
                PropertyChanges { // "expanded"状態になったときのプロパティ変更
                    target: myRect
                    width: 200
                    height: 200
                    color: "blue"
                    x: 100
                    y: 100
                }
            }
        ]

        // 状態遷移時のアニメーション定義
        transitions: [
            Transition {
                from: "" // デフォルトの状態から
                to: "expanded" // "expanded"状態へ
                PropertyAnimation { // プロパティアニメーション
                    target: myRect // アニメーション対象
                    properties: "width,height,color,x,y" // アニメーションさせるプロパティ
                    duration: 500 // アニメーション時間(ミリ秒)
                    easing.type: Easing.OutQuart // イージング関数
                }
            },
            Transition {
                from: "expanded" // "expanded"状態から
                to: "" // デフォルトの状態へ
                PropertyAnimation {
                    target: myRect
                    properties: "width,height,color,x,y"
                    duration: 500
                    easing.type: Easing.OutQuart
                }
            }
        ]

        // クリックで状態を切り替える
        MouseArea {
            anchors.fill: parent
            onClicked: {
                if (myRect.state === "expanded") {
                    myRect.state = ""; // デフォルトの状態に戻す
                } else {
                    myRect.state = "expanded"; // "expanded"状態へ
                }
            }
        }
    }
}

解説

  • MouseArea: myRectをクリックすると、myRect.stateプロパティが切り替わり、それに応じて定義されたTransitionが実行されます。
  • transitions: 状態が変化する際のアニメーションを定義します。
    • 最初のTransitionは、デフォルトの状態("")から"expanded"状態へ遷移する際のアニメーションです。PropertyAnimationを使って、指定されたプロパティ(width,height,color,x,y)が0.5秒かけて滑らかに変化するように設定しています。
    • 2番目のTransitionは、"expanded"状態からデフォルトの状態へ戻る際のアニメーションです。
  • states: myRectが持つ「状態」を定義します。ここでは"expanded"という状態を定義し、その状態になったときにmyRectwidth, height, color, x, yがどのように変化するかを指定します。

例2:reversible プロパティの使用と複数のアニメーション

reversibleプロパティを使うと、往復のアニメーションを簡潔に記述できます。また、複数のアニメーションをParallelAnimationで同時に実行する例です。

import QtQuick 2.15
import QtQuick.Window 2.15

Window {
    width: 400
    height: 300
    visible: true
    title: "Reversible and Parallel Animation"

    Rectangle {
        id: animatedRect
        width: 100
        height: 100
        color: "orange"
        x: 50
        y: 50
        radius: 0 // 角丸

        states: [
            State {
                name: "active"
                PropertyChanges {
                    target: animatedRect
                    width: 150
                    height: 150
                    color: "purple"
                    rotation: 90 // 回転
                    radius: 20 // 角丸
                    opacity: 0.7 // 透明度
                    x: 200
                    y: 100
                }
            }
        ]

        transitions: [
            Transition {
                from: "*" // 任意の状態から
                to: "*"   // 任意の状態へ
                reversible: true // 往復アニメーションを自動で定義

                // 複数のアニメーションを並行して実行
                ParallelAnimation {
                    // サイズ、位置、回転のアニメーション
                    NumberAnimation {
                        properties: "width,height,x,y,rotation"
                        duration: 600
                        easing.type: Easing.InOutSine
                    }
                    // 色のアニメーション
                    ColorAnimation {
                        property: "color"
                        duration: 600
                    }
                    // 角丸のアニメーション
                    NumberAnimation {
                        property: "radius"
                        duration: 600
                    }
                    // 透明度のアニメーション
                    NumberAnimation {
                        property: "opacity"
                        duration: 600
                    }
                }
            }
        ]

        MouseArea {
            anchors.fill: parent
            onClicked: {
                if (animatedRect.state === "active") {
                    animatedRect.state = "";
                } else {
                    animatedRect.state = "active";
                }
            }
        }
    }
}

解説

  • from: "*", to: "*": 任意の状態から任意の状態への遷移にこのTransitionが適用されます。これは非常に汎用的な設定であり、特定の状態間でのみアニメーションさせたい場合は状態名を明示的に指定します。
  • ParallelAnimation: 複数のPropertyAnimationNumberAnimation, ColorAnimationなど)をParallelAnimationの中に含めることで、それらのアニメーションを同時に実行させることができます。これにより、色、サイズ、位置、回転、角丸、透明度など、複数のプロパティが同時に滑らかに変化します。
  • reversible: true: これを設定することで、fromからtoへの遷移だけでなく、toからfromへの逆遷移に対しても同じアニメーションが適用されます。これにより、Transitionの記述量が減り、コードが簡潔になります。

例3:Behavior on を使った個別のプロパティアニメーション

Item.transitionsは状態遷移全体を制御するのに対し、Behavior on <property>は特定のプロパティが変更されたときにのみアニメーションを適用します。これは、状態を使用しないシンプルなプロパティ変更に便利です。

import QtQuick 2.15
import QtQuick.Window 2.15

Window {
    width: 400
    height: 300
    visible: true
    title: "Behavior on Property Animation"

    Rectangle {
        id: clickRect
        width: 150
        height: 150
        color: "lightgray"
        x: 50
        y: 50

        // "color"プロパティが変更されたときにアニメーションを適用
        Behavior on color {
            ColorAnimation { duration: 400 } // 色の変化に0.4秒のアニメーション
        }

        // "width"プロパティが変更されたときにアニメーションを適用
        Behavior on width {
            NumberAnimation { duration: 300; easing.type: Easing.OutElastic } // 幅の変化に0.3秒の弾むようなアニメーション
        }

        // "rotation"プロパティが変更されたときにアニメーションを適用
        Behavior on rotation {
            NumberAnimation { duration: 500; easing.type: Easing.OutBounce } // 回転に0.5秒のバウンドするようなアニメーション
        }

        MouseArea {
            anchors.fill: parent
            onClicked: {
                // プロパティを直接変更すると、対応するBehaviorが自動的にアニメーションを適用
                if (clickRect.color === "lightgray") {
                    clickRect.color = "gold";
                    clickRect.width = 200;
                    clickRect.rotation = 45;
                } else {
                    clickRect.color = "lightgray";
                    clickRect.width = 150;
                    clickRect.rotation = 0;
                }
            }
        }
    }
}

解説

  • MouseArea.onClicked: ここではclickRect.stateを変更する代わりに、プロパティを直接変更しています。Behavior onはその変更を検知し、それぞれ独自のアニメーションを実行します。
  • Behavior on rotation { ... }: clickRect.rotationプロパティの値が変更されると、NumberAnimationが適用されます。
  • Behavior on width { ... }: 同様に、clickRect.widthプロパティの値が変更されると、NumberAnimationが適用されます。
  • Behavior on color { ... }: clickRect.colorプロパティの値が変更されると、自動的にColorAnimationが適用されます。

このBehavior onは、Item.transitionsとは異なるアプローチでアニメーションを提供しますが、プロパティ変更に特化したアニメーションが必要な場合に非常に役立ちます。Item.transitionsが「状態の変化」をアニメーションするのに対し、Behavior onは「特定のプロパティの変化」をアニメーションすると考えると良いでしょう。



主な代替方法としては、以下の3つが挙げられます。

  1. Behavior on <property> (プロパティ変更時の振る舞い)
  2. スタンドアロンアニメーション (Standalone Animations)
  3. シグナルハンドラ内のアニメーション (Animations in Signal Handlers)

それぞれ詳しく見ていきましょう。

Behavior on <property> (プロパティ変更時の振る舞い)

これは前回の説明でも少し触れましたが、Item.transitionsの次に一般的なアニメーション方法です。

特徴

  • 状態管理不要
    状態(State)を明示的に定義する必要がないため、シンプルなプロパティ変更のアニメーションには簡潔です。
  • 柔軟性
    個々のプロパティに対して異なるアニメーション(異なるdurationeasing)を設定できます。
  • 自動トリガー
    プロパティの値が変更されると、自動的にアニメーションが開始されます。JavaScriptからの代入、C++からのプロパティ変更、またはQML内のバインディングによってプロパティが変更された場合でも機能します。
  • 宣言的
    プロパティの変更に対してアニメーションを宣言的に記述できます。

使用例

import QtQuick 2.15
import QtQuick.Window 2.15

Window {
    width: 400
    height: 300
    visible: true
    title: "Behavior on Example"

    Rectangle {
        id: myRect
        width: 100
        height: 100
        color: "red"
        x: 50
        y: 50

        // x プロパティが変更されたらアニメーション
        Behavior on x {
            NumberAnimation { duration: 500; easing.type: Easing.OutBounce }
        }

        // y プロパティが変更されたらアニメーション
        Behavior on y {
            NumberAnimation { duration: 500; easing.type: Easing.OutBounce }
        }

        // color プロパティが変更されたらアニメーション
        Behavior on color {
            ColorAnimation { duration: 300 }
        }

        MouseArea {
            anchors.fill: parent
            onClicked: {
                // クリックするたびにx, y, colorを変更
                if (myRect.x === 50) {
                    myRect.x = 200;
                    myRect.y = 150;
                    myRect.color = "blue";
                } else {
                    myRect.x = 50;
                    myRect.y = 50;
                    myRect.color = "red";
                }
            }
        }
    }
}

Item.transitionsとの使い分け

  • Behavior on <property>: 特定のプロパティの変更を個別にアニメーションしたい場合に適しています。例えば、ドラッグ&ドロップでアイテムの位置が変化する際のアニメーションなど。状態を定義するほどではない、きめ細かいアニメーションに便利です。
  • Item.transitions: 複数のプロパティが同時に変化する「状態」を定義し、その状態間を遷移する際の一貫したアニメーションを提供したい場合に適しています。UI全体の状態遷移アニメーションに適しています。

スタンドアロンアニメーション (Standalone Animations)

アニメーション要素(例: PropertyAnimation, SequentialAnimation, ParallelAnimationなど)を独立して定義し、JavaScriptコードから明示的に開始・停止させる方法です。

特徴

  • 柔軟な開始条件
    プロパティの変更や状態の変化だけでなく、任意の条件(例: サーバーからのデータ受信後、一定時間経過後など)でアニメーションを開始できます。
  • 再利用性
    独立したアニメーションとして定義することで、複数の場所から呼び出すことが可能です。
  • 明示的な制御
    start(), stop(), pause(), resume()などのメソッドを使って、アニメーションの実行をJavaScriptから完全に制御できます。

使用例

import QtQuick 2.15
import QtQuick.Window 2.15

Window {
    width: 400
    height: 300
    visible: true
    title: "Standalone Animation Example"

    Rectangle {
        id: animatedBox
        width: 100
        height: 100
        color: "lightgreen"
        x: 50
        y: 50

        // xとyを同時にアニメーションさせるParallelAnimationを定義
        ParallelAnimation {
            id: moveAnimation
            NumberAnimation { target: animatedBox; property: "x"; to: 250; duration: 800; easing.type: Easing.OutQuad }
            NumberAnimation { target: animatedBox; property: "y"; to: 200; duration: 800; easing.type: Easing.OutQuad }
            // アニメーション終了時の処理
            onStopped: {
                console.log("Animation stopped!");
                // 終了したら位置をリセット
                animatedBox.x = 50;
                animatedBox.y = 50;
            }
        }

        MouseArea {
            anchors.fill: parent
            onClicked: {
                // クリックでアニメーションを開始
                moveAnimation.start();
            }
        }
    }
}

Item.transitionsとの使い分け

  • スタンドアロンアニメーションは、特定のアクション(ボタンクリック、データロード完了など)に応じて一時的なアニメーションを実行したい場合や、アニメーションの開始・停止・一時停止を細かく制御したい場合に適しています。また、単一のUI要素で複数のアニメーションシーケンスを持つ場合にも利用されます。
  • Item.transitionsは、状態が明確に定義されており、その状態間の「スムーズな移行」が主目的の場合に最適です。

シグナルハンドラ内のアニメーション (Animations in Signal Handlers)

これはスタンドアロンアニメーションのバリエーションとも言えますが、onClicked, onPressAndHoldなどのシグナルハンドラ内で直接アニメーションを定義し、実行する方法です。

特徴

  • シンプル
    短いアニメーションや、使い捨てのアニメーションに適しています。
  • イベント駆動
    イベントが発生したときにのみアニメーションが実行されます。
  • インライン定義
    シグナルハンドラ内でアニメーションを直接定義できるため、コードがまとまります。

使用例

import QtQuick 2.15
import QtQuick.Window 2.15

Window {
    width: 400
    height: 300
    visible: true
    title: "Animation in Signal Handler Example"

    Rectangle {
        id: pulseRect
        width: 100
        height: 100
        color: "pink"
        anchors.centerIn: parent

        MouseArea {
            anchors.fill: parent
            onClicked: {
                // クリックされるたびにサイズが大きくなり、元に戻るアニメーション
                SequentialAnimation {
                    // targetとpropertyは、アニメーションが定義されているコンテキストから推論される
                    // pulseRect.widthに対してアニメーションが適用される
                    NumberAnimation { to: 120; duration: 100 } // 少し大きく
                    NumberAnimation { to: 100; duration: 200 } // 元に戻る
                }.start() // アニメーションを即座に開始
            }
            onPressed: {
                // 押されたら色が変化
                ColorAnimation {
                    target: pulseRect
                    property: "color"
                    to: "darkred"
                    duration: 50
                }.start()
            }
            onReleased: {
                // 離されたら色が元に戻る
                ColorAnimation {
                    target: pulseRect
                    property: "color"
                    to: "pink"
                    duration: 100
                }.start()
            }
        }
    }
}

解説

  • targetpropertyを省略できるのは、アニメーションがpulseRectのコンテキスト内で定義されており、それらが暗黙的に推論されるためです。
  • onClickedハンドラ内でSequentialAnimationを定義し、.start()を呼び出してアニメーションを即座に開始しています。

Item.transitionsとの使い分け

  • シグナルハンドラ内のアニメーションは、ユーザーのアクション(クリック、ホバーなど)に直接反応する短いフィードバックアニメーションや、非常に局所的なアニメーションに適しています。状態管理を伴わない、単発のアニメーションに向いています。
  • Item.transitionsは、アプリケーションの明確な状態(例: "ログイン済み", "設定画面", "エラー状態"など)があり、それらの状態間の視覚的な連続性を重視する場合に最適です。

Item.transitionsはQMLの強力な状態管理とアニメーションの連携機能ですが、すべてのケースに最適なわけではありません。

  • シグナルハンドラ内のアニメーション: 特定のユーザーイベントに即座に反応する、短くてシンプルなアニメーションに最適。
  • スタンドアロンアニメーション: JavaScriptから明示的に制御したい、再利用したい、あるいは複雑なアニメーションシーケンスを組みたい場合に適している。
  • Behavior on <property>: 特定のプロパティの値が変更されたときに自動でアニメーションしたい場合に便利。