7

目に見えるアニメーションを連続させようとしています。myModel.move() を 2 回呼び出す JavaScript 関数があります。myModel を表示する GridView があり、「Behavior on x」アニメーションがあるため、動きを視覚的に確認できます。ただし、両方の動きのアニメーションは並行して実行されます (それらの間の小さな遅延は目立ちません)。

私のアイデアは、開始されたアニメーションの数と、既に終了したアニメーションの数のカウンターを追加することでした。このようなもの;

Behavior on x {
    NumberAnimation {
        id: animationX;
        duration: 500;
        onRunningChanged: {
            if (animationX.running) {
                console.log("Animation start");
                myModel.busy = myModel.busy + 1
            } else {
                console.log("Animation stop");
                myModel.busy = myModel.busy - 1
            }
        }
    }
}

これは期待どおりに機能します。次に、JavaScript 関数にループを追加して、すべてのアニメーションが終了するまで待機します。

ListModel {
    id: myModel
    property int busy: 0
    function doSomething() {
        myModel.move(...)
        while (myModel.busy) {}
        myModel.move(...)
    }
}

これが問題です。最初の move() の後、必要なすべてのアニメーションが開始されたことがわかりますが、何も表示されず、アニメーションも終了していません。ある種のデッドロックがあります。これを解決するには?

4

2 に答える 2

2
function doSomething() {
    myModel.move(...)
    while (myModel.busy) {}
    myModel.move(...)
}

私はjavascriptが苦手です。しかし、なぜあなたはビジーループをするのですか? 私は2つの機能を作成します。

  • 最初に makemyModel.move()を作成し、将来のイベントに備えてフィールドを準備します (クリックされる非表示のボタンを作成するなど)。
  • 2 つ目は、将来のイベントが作成されたときに呼び出されます。上記の例では になりますOnclick

onRunningChangedイベントハンドラーの定義のようです。onModelIdle同じを作成しないのはなぜですか、次のように呼び出しましょう

...
   onRunningChanged: {
        if (animationX.running) {
            console.log("Animation start");
            myModel.busy = myModel.busy + 1
        } else {
            console.log("Animation stop");
            myModel.busy = myModel.busy - 1
            if(myModel.busy == 0)
              // don't know the code, but trigger the onModelIdle event which 
              // be handled below
        }
    }
...

ListModel {
   id: myModel
   ...

   onModelIdle{
       myModel.move(...)
   }
}
于 2012-09-07T13:32:57.520 に答える
1

#UmNyobe からの回答に基づく実用的なソリューションを次に示します。QML は宣言型言語であるため、反復的な問題には問題があります。どんなコメントでも大歓迎です。おそらく、誰かが同じ効果を生み出すより良い(より読みやすい)純粋なQMLプログラムを提案できるでしょう。

import QtQuick 1.1
GridView {
    id: mainGrid
    cellWidth: 165; cellHeight: 95
    width: 5*cellWidth; height: 4*cellHeight
    model: myModel
    delegate: myButton
    property string animate: "no"
    property int busy: 0
    signal busyPlus
    signal busyMinus
    onBusyPlus: {
        busy++
    }
    onBusyMinus: {
        busy--
        if (busy == 0) mainGrid.model.algorithm()
    }
    ListModel {
        id: myModel
        property int step: 0
        property int one: 0
        function createModel() {
            for (var i=1; i<=20; i++) {
                append({"display": i})
            }
        }
        function algorithm() {
            if (step == 0) {
                move(0,19,1)
                one = 0
                step++
            }
            else if (step == 1) {
                if (one < 19) {
                    move(one,one+1,1)
                    one++
                    if (one == 19) step++
                }
            }
            else if (step == 2) {
                move(0,1,1)
                move(5,6,1)
                move(10,11,1)
                move(15,16,1)
                step++
            }
        }
        Component.onCompleted: {
            createModel()
            mainGrid.animate = "yes"
            algorithm()
        }
    }
    Component {
        id: myButton
        Item {
            id: item
            width: mainGrid.cellWidth-5; height: mainGrid.cellHeight-5;
            Rectangle {
                id: box
                parent: mainGrid
                x: item.x; y: item.y;
                width: item.width; height: item.height;
                border.width: 1
                Text {
                    anchors.centerIn: parent
                    text: display
                    font.pixelSize: 48
                }
                Behavior on x {
                    enabled: mainGrid.animate == "yes"
                    NumberAnimation {
                        id: animationX;
                        duration: 1000;
                        onRunningChanged: {
                            if (animationX.running) mainGrid.busyPlus()
                            else mainGrid.busyMinus()
                        }
                    }
                }
                Behavior on y {
                    enabled: mainGrid.animate == "yes"
                    NumberAnimation {
                        id: animationY;
                        duration: 1000;
                        onRunningChanged: {
                            if (animationY.running) mainGrid.busyPlus()
                            else mainGrid.busyMinus()
                        }
                    }
                }
            }
        }
    }
}
于 2013-01-02T14:31:56.950 に答える