Последовательная анимация в TornadoFX?

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

timeline { keyframe(Duration.seconds(0.5)) { keyvalue(firstImg.scaleXProperty(), 1.0, interpolator = Interpolator.EASE_BOTH) keyvalue(firstImg.scaleYProperty(), 1.0, interpolator = Interpolator.EASE_BOTH) keyvalue(firstImg.rotateProperty(), 0.0, interpolator = Interpolator.EASE_BOTH) } keyframe(Duration.seconds(0.5)) { keyvalue(secondImg.scaleXProperty(), 1.0, interpolator = Interpolator.EASE_BOTH) keyvalue(secondImg.scaleYProperty(), 1.0, interpolator = Interpolator.EASE_BOTH) keyvalue(secondImg.rotateProperty(), 0.0, interpolator = Interpolator.EASE_BOTH) } keyframe(Duration.seconds(0.5)) { keyvalue(thirdImg.scaleXProperty(), 1.0, interpolator = Interpolator.EASE_BOTH) keyvalue(thirdImg.scaleYProperty(), 1.0, interpolator = Interpolator.EASE_BOTH) keyvalue(thirdImg.rotateProperty(), 0.0, interpolator = Interpolator.EASE_BOTH) } keyframe(Duration.seconds(0.5)) { keyvalue(fourthImg.scaleXProperty(), 1.0, interpolator = Interpolator.EASE_BOTH) keyvalue(fourthImg.scaleYProperty(), 1.0, interpolator = Interpolator.EASE_BOTH) keyvalue(fourthImg.rotateProperty(), 0.0, interpolator = Interpolator.EASE_BOTH) } } 

Это запускает их все сразу, но я хотел бы запускать каждую анимацию после того, как она закончилась! Я не могу понять, как это сделать .. ( извините, если это очевидно, я очень новичок в Kotlin и Java вообще! )

Я вижу, что ключевой кадр имеет свойство onFinished но я не могу понять, на что я должен был его настроить . Есть лучший способ сделать это? Спасибо!

Существует класс JavaFX «SequentialTransition», который будет последовательно выполнять ваши временные рамки. Вам нужно отключить автозапуск TornadoFX с флагом, переданным в построитель временной шкалы. Проверьте ParallelTransition, если вы хотите запустить все это сразу, используя аналогичный шаблон кодирования.

 class STTest : View("My View") { val r1 = Rectangle(20.0, 20.0, Color.RED) val r2 = Rectangle(20.0, 20.0, Color.YELLOW) val r3 = Rectangle(20.0, 20.0, Color.GREEN) val r4 = Rectangle(20.0, 20.0, Color.BLUE) override val root = vbox { button("Animate") { setOnAction { val t1 = timeline(false) { keyframe(Duration.seconds(0.5)) { keyvalue(r1.translateXProperty(), 50.0, interpolator = Interpolator.EASE_BOTH) } } val t2 = timeline(false) { keyframe(Duration.seconds(0.5)) { keyvalue(r2.translateXProperty(), 100.0, interpolator = Interpolator.EASE_BOTH) } } val t3 = timeline(false) { keyframe(Duration.seconds(0.5)) { keyvalue(r3.translateXProperty(), 150.0, interpolator = Interpolator.EASE_BOTH) } } val t4 = timeline(false) { keyframe(Duration.seconds(0.5)) { keyvalue(r4.translateXProperty(), 200.0, interpolator = Interpolator.EASE_BOTH) } } /* functions look better val st = SequentialTransition() st.children += t1 st.children += t2 st.children += t3 st.children += t4 st.play() */ t1.then(t2).then(t3).then(t4).play() } } pane { add(r1) add(r2) add(r3) add(r4) } } } 

Основываясь на структуре, предложенной @ tornadofx-fan, я добавил разработчиков для последовательного перехода и параллельного перехода, поэтому, начиная с TornadoFX 1.7.9, вы можете сделать то же самое:

 class TransitionViews: View() { val r1 = Rectangle(20.0, 20.0, Color.RED) val r2 = Rectangle(20.0, 20.0, Color.YELLOW) val r3 = Rectangle(20.0, 20.0, Color.GREEN) val r4 = Rectangle(20.0, 20.0, Color.BLUE) override val root = vbox { button("Animate").action { sequentialTransition { timeline { keyframe(0.5.seconds) { keyvalue(r1.translateXProperty(), 50.0, interpolator = Interpolator.EASE_BOTH) } } timeline { keyframe(0.5.seconds) { keyvalue(r2.translateXProperty(), 100.0, interpolator = Interpolator.EASE_BOTH) } } timeline { keyframe(0.5.seconds) { keyvalue(r3.translateXProperty(), 150.0, interpolator = Interpolator.EASE_BOTH) } } timeline { keyframe(0.5.seconds) { keyvalue(r4.translateXProperty(), 200.0, interpolator = Interpolator.EASE_BOTH) } } } } pane { add(r1) add(r2) add(r3) add(r4) } } } 

Создатель временной шкалы внутри этих переходов не воспроизводится автоматически, тогда как сам переход автоматически воспроизводится, когда строитель завершается. Вы можете передать play=false в конструктор переходов, чтобы отключить автовоспроизведение.

Также обратите внимание на использование 0.5.seconds для создания объектов Duration 🙂

В этом случае, когда вы просто устанавливаете масштабы и вращения, в библиотеке уже есть некоторые помощники. Это должно сработать для вас:

 val time = 0.5.seconds firstImg.scale(time, Point2D(1.0, 1.0), play = false).and(firstImg.rotate(time, 0.0, play = false)) .then(secondImg.scale(time, Point2D(1.0, 1.0), play = false).and(secondImg.rotate(time, 0.0, play = false))) .then(thirdImg.scale(time, Point2D(1.0, 1.0), play = false).and(thirdImg.rotate(time, 0.0, play = false))) .then(fourthImg.scale(time, Point2D(1.0, 1.0), play = false).and(fourthImg.rotate(time, 0.0, play = false))) .play() 

play = false везде требуется, так как эти помощники были разработаны для простых одноразовых автоиграющих анимаций.

редактировать

После обсуждения в Slack , это может быть упрощено в будущем выпуске, поэтому вышеизложенное может в конечном итоге быть таким простым, как

 val time = 0.5.seconds listOf( firstImg.scale(time, 1 p 1) and firstImg.rotate(time, 0), secondImg.scale(time, 1 p 1) and secondImg.rotate(time, 0), thirdImg.scale(time, 1 p 1) and thirdImg.rotate(time, 0), fourthImg.scale(time, 1 p 1) and fourthImg.rotate(time, 0) ).playSequential() 

Смотрите заметки о выпуске для получения дополнительной информации!

Другое редактирование

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

 val time = 0.5.seconds SequentialTransition( firstImg.scale(time, Point2D(1.0, 1.0), play = false).and(firstImg.rotate(time, 0.0, play = false)). secondImg.scale(time, Point2D(1.0, 1.0), play = false).and(secondImg.rotate(time, 0.0, play = false)), thirdImg.scale(time, Point2D(1.0, 1.0), play = false).and(thirdImg.rotate(time, 0.0, play = false)), fourthImg.scale(time, Point2D(1.0, 1.0), play = false).and(fourthImg.rotate(time, 0.0, play = false)) ).play() 
  • TornadoFx: Что делает лучше FXML или type-CSS
  • Как создать заставку в tornadofx
  • Текст ярлыка не обновляется, хотя поток пользовательского интерфейса кажется отзывчивым
  • Серия Autosize ScatterChart
  • TornadoFX как связать стиль узла (или styleClass) с свойством?
  • Невозможно получить узел в центре в StackPane с помощью TornadoFX
  • tornadofx EventBus развернуть таблицу с использованием объекта tableview
  • TornadoFX - удалить элемент с помощью контекстного меню правой кнопкой мыши
  • Плавная прокрутка в JavaFX TableView
  • java.lang.ClassNotFoundException: Не нашел класс «com.my.app.example.Main» по пути: DexPathList
  • TornadoFX: текст метки не обновляется
  • Interesting Posts

    Kotlin: построить значение производного общего типа в базовом классе

    Является ли котлин функциональным и процедурным?

    Не удается отправить многостраничные данные / данные формы с помощью Volley

    найдены дублирующиеся устройства Bluetooth. Я здесь дважды погружаюсь? также может обновлять recyclerview

    Методы статического провайдера Dagger 2 в Котлине

    Разделение кода Kotlin2JavaScript на несколько модулей maven

    Kotlin: Может ли абстрактный суперкласс иметь абстрактный конструктор?

    Неразрешенный опорный кинжал 2 + kotlin + android gradle

    Как создать кнопку в Kotlin, которая открывает новую активность (Android Studio)?

    Могу ли я применять функцию infix внутри собственного класса без этого?

    Являются ли числовые операции с использованием Kotlin столь же быстрыми, как эквивалент с Java-примитивами?

    Как я могу автоматически присвоить переменную переменной по типу в реальном шаблоне?

    Как получить данные из пользовательской таблицы в Corda

    эквивалентный интерфейс java на kotlin

    Как выбрать, какая перегрузка Java переопределить в производном классе Kotlin?

    Давайте будем гением компьютера.