2012-09-07 112 views
5

我正在嘗試製作可見的動畫。我有一個JavaScript函數,它調用myModel.move()兩次。我有一個GridView來顯示我的模型,我有「X上的行爲」動畫,因此我可以直觀地看到動作。但是,這兩種運動動畫片都是並列運行的(它們之間的小延遲並不明顯)。QML:等到動畫完成

我的想法是添加一個有多少動畫開始的計數器,以及其中有多少個已經完成。像這樣的東西;

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(...) 
    } 
} 

這是問題所在。我可以看到,第一次移動()所有必要的動畫開始後,但沒有什麼可以看到,沒有動畫完成。我有一種僵局。如何解決這個問題?

回答

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

我對javascript不好。但你爲什麼忙着循環?我會創建2個函數。

  • 第一個作出myModel.move(),那麼對於未來事件準備字段(如創建一個隱藏按鈕,將被點擊)
  • 創建將來事件時,第二個將被調用。以上例爲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(...) 
    } 
} 
+0

是的,我知道...簡化問題產生簡化的答案:-(其實,我想有許多不同的連續myModel.move(...)調用。但是,你的建議是可用的(見解決方案我在下面發佈) – meolic

+0

如果你想保持性能,一個繁忙的循環並不是一個好主意 – trusktr

+0

@trusktr和你在哪看到我說這是一個好主意? – UmNyobe

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() 
         } 
        } 
       } 
      } 
     } 
    } 
}