2014-09-27 5 views
3

Я хочу изменить состояние после того, как анимация перехода завершена. У меня есть следующий код, который достигает эту цель, хотя, кажется, своего рода хак:Изменение состояния после завершения анимации перехода

import QtQuick 2.3 
import QtQuick.Controls 1.2 
import QtQuick.Controls.Styles 1.2 

Rectangle { 
    id: root 
    width: 400 
    height: 400 

    Rectangle { 
     id: rect 
     color: "blue" 
     width: 50 
     height: 50 
     anchors.centerIn: parent 

     MouseArea { 
      anchors.fill: parent 
      onClicked: rect.state = "animating" 
     } 

     states: [ 
      State { 
       name: "animating" 

       PropertyChanges { 
        target: rect 
        rotation: 360 
       } 
      }, 
      State { 
       name: "shrinking" 

       PropertyChanges { 
        target: rect 
        scale: 0 
       } 
      } 
     ] 

     transitions: [ 
      Transition { 
       from: "" 
       to: "animating" 

       SequentialAnimation { 
        RotationAnimation { 
         duration: 500 
        } 
        ScriptAction { 
         script: rect.state = "shrinking" 
        } 
       } 
      }, 
      Transition { 
       from: "animating" 
       to: "shrinking" 

       NumberAnimation { 
        property: "scale" 
        duration: 500 
       } 
      } 
     ] 
    } 
} 

Есть ли лучше способ сделать это без использования ScriptAction? Обратите внимание, что мне нужно второе состояние, и я не хочу просто консолидировать анимацию масштаба в SequentialAnimation перехода animating.

+0

Этот вопрос является дубликатом https://stackoverflow.com/questions/22902769/how-to-switch-to-another-state-at- end-of-a-transition-in-qml, но существующее решение более чистое, чем ответ на исходный вопрос. – cmannett85

+0

Мне даже не нравится мое решение, поэтому я надеюсь, что есть лучший. : p – Mitch

+0

Тот факт, что ваше состояние называется «сжатием» вместо «сжатого», является признаком того, что они не являются реальными состояниями, а переходы реализуются как состояния. Не можете ли вы объединить оба перехода с помощью SequentialAnimation? – jturcotte

ответ

-1

несколько иной подход, чтобы установить shrinking состояние в animating состоянии, и использовать PropertyAction, чтобы заставить изменение состояния должно произойти в конце перехода:

 State { 
      name: "animating" 

      PropertyChanges { 
       target: rect 
       rotation: 360 
      } 
      PropertyChanges { 
       target: rect 
       state: "shrinking" 
      } 

и

 Transition { 
      SequentialAnimation { 
       RotationAnimation { 
        duration: 500 
       } 
       PropertyAction { 
        target: rect 
        property: "state" 
       } 
      } 
     } 

Обратите внимание, что я согласен с jturcotte на его оценке использования этих состояний здесь.

+0

Это не работает: 'QML StateGroup: не может применить изменение состояния как часть определения состояния.' – Mitch

+0

Не знал, что это не работает для изменений состояния самого элемента (имеет смысл, хотя) , Я часто использую этот подход, когда корневой элемент запускает изменения состояния разных детей при изменении состояния. Вы можете выполнить эту работу, например. используя два вспомогательных 'Item',' shrinkstate' и 'animatingstate', определяя изменения состояния там, а затем вызывая их изменения состояния из родительского прямоугольника. Здесь очень громоздко, но может быть более чистым решением, если все остальные изменения qml и состояния становятся более активными. – Adversus

0

Правильный способ заключается в изменении состояния в обработчике runningChanged перехода при прохождении к ложному, чем завершение анимации. сделать что у вас есть два решения:

Sol 1. Использование connections (вы получите предупреждение о доли не уведомляемом собственности, игнорировать его)

Connections{ 
      target:rect.transitions[0] 

      onRunningChanged:{ 
       if(rect.transitions[0].running === false) 
       { 
        rect.state = "shrinking" 
       } 
      } 
     } 

код будет:

import QtQuick 2.3 
import QtQuick.Controls 1.2 
import QtQuick.Controls.Styles 1.2 

Rectangle { 
    id: root 
    width: 400 
    height: 400 

    Rectangle { 
     id: rect 
     color: "blue" 
     width: 50 
     height: 50 
     anchors.centerIn: parent 

     MouseArea { 
      anchors.fill: parent 
      onClicked: rect.state = "animating" 
     } 

     states: [ 
      State { 
       name: "animating" 

       PropertyChanges { 
        target: rect 
        rotation: 360 
       } 
      }, 
      State { 
       name: "shrinking" 

       PropertyChanges { 
        target: rect 
        scale: 0 
       } 
      } 
     ] 
     Connections{ 
      target:rect.transitions[0] 

      onRunningChanged:{ 
       if(rect.transitions[0].running === false) 
       { 
        rect.state = "shrinking" 
       } 
      } 
     } 
     transitions: [ 
      Transition { 
       from: "" 
       to: "animating" 
        RotationAnimation { 
         duration: 500 
        } 
      }, 
      Transition { 
       from: "animating" 
       to: "shrinking" 

       NumberAnimation { 
        property: "scale" 
        duration: 500 
       } 
      } 
     ] 
    } 
} 

раствор 2: изменить состояние, в runningchanged обработчика при переходе непосредственно:

import QtQuick 2.3 
import QtQuick.Controls 1.2 
import QtQuick.Controls.Styles 1.2 

Rectangle { 
    id: root 
    width: 400 
    height: 400 

    Rectangle { 
     id: rect 
     color: "blue" 
     width: 50 
     height: 50 
     anchors.centerIn: parent 

     MouseArea { 
      anchors.fill: parent 
      onClicked: rect.state = "animating" 
     } 

     states: [ 
      State { 
       name: "animating" 

       PropertyChanges { 
        target: rect 
        rotation: 360 
       } 
      }, 
      State { 
       name: "shrinking" 

       PropertyChanges { 
        target: rect 
        scale: 0 
       } 
      } 
     ] 

     transitions: [ 
      Transition { 
       from: "" 
       to: "animating" 

        RotationAnimation { 
         duration: 500 
        } 
        onRunningChanged:{ 
         if(running === false) 
         { 
          rect.state = "shrinking" 
         } 
        } 
      }, 
      Transition { 
       from: "animating" 
       to: "shrinking" 

       NumberAnimation { 
        property: "scale" 
        duration: 500 
       } 
      } 
     ] 
    } 
} 

Я предпочитаю первое решение (Connections) потому что это более общий

+0

Я бы не назвал это правильным способом, точно так же, как мое решение не кажется правильным. Я все еще не думаю, что есть хороший способ сделать это. – Mitch

+0

Я имел в виду надлежащим образом, что я думаю, что разработчик Qt создал сигнал runningChanged, который будет использоваться таким образом, это лучше, чем использование ScriptAction. если не то, что является точкой испускания этого сигнала :) – Mido

+1

Существует множество способов изменения состояния, но они являются либо императивными, а не декларативными, или они просто чувствуют ... yucky. : p Я думаю, что свойство 'nextState' было бы очень приятно иметь в объекте' State'. Мне нужно придумать лучший пример, хотя, как я думаю, @jturcotte правильно относится к моей оригинальной, поскольку это может быть всего лишь две анимации. – Mitch