2 Replies Latest reply: Jan 22, 2013 5:47 PM by James_D RSS

    Start, stop a ParallelTransition with changed Duration in PathTransition

    Peter Rogge
      Hi,
      im writing a little game where i try to stop (and restart with faster duration) the rotation from 5 circles which rotate along a bigger circle. When the mouse is over from one of the circles then then animation (rotation) stops. When the mouse leave this circle the animation restart with faster duration, means the circles should rotate faster. I can managed to stop and restart the rotation with the same rotationspeed.

      But when i try to change the rotationspeed (which i can) then the circles make a little jump, because the rotationspeed is changed. I restart the movement from the circles with parallelTransition.playFrom(currentTime), but the currentTime was catched from the previous duration.

      So my question is how can i restart the ParallelTransition with faster duration in the PathTranstion and the circles don't jump after every restart?
      public class XJavaFXApplication14 extends Application {
          
          @Override
          public void start(Stage stage) throws Exception {
              Parent root = FXMLLoader.load(getClass().getResource("Sample.fxml"));
              
              Scene scene = new Scene(root);
              
              stage.setScene(scene);
              stage.show();
          }
      
          /**
           * The main() method is ignored in correctly deployed JavaFX application.
           * main() serves only as fallback in case the application can not be
           * launched through deployment artifacts, e.g., in IDEs with limited FX
           * support. NetBeans ignores main().
           *
           * @param args the command line arguments
           */
          public static void main(String[] args) {
              launch(args);
          }
      }
      <?xml version="1.0" encoding="UTF-8"?>
      
      <?import java.lang.*?>
      <?import java.util.*?>
      <?import javafx.scene.*?>
      <?import javafx.scene.control.*?>
      <?import javafx.scene.layout.*?>
      <?import javafx.scene.paint.*?>
      <?import javafx.scene.shape.*?>
      
      <AnchorPane id="AnchorPane" fx:id="root" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml" fx:controller="xjavafxapplication14.SampleController">
        <children>
          <Circle fx:id="cShapeRed" layoutX="300.0" layoutY="200.0" radius="100.0" stroke="BLACK" strokeType="INSIDE">
            <fill>
              <Color blue="0.400" green="0.400" opacity="0.000" red="1.000" fx:id="x1" />
            </fill>
          </Circle>
          <Circle fx:id="cShapeViolett" fill="$x1" layoutX="300.0" layoutY="200.0" radius="100.0" stroke="TRANSPARENT" strokeType="INSIDE" />
          <Circle fx:id="cShapeGreen" fill="$x1" layoutX="300.0" layoutY="200.0" radius="100.0" stroke="TRANSPARENT" strokeType="INSIDE" />
          <Circle id="cShapeGreen" fx:id="cShapeYellow" fill="$x1" layoutX="300.0" layoutY="200.0" radius="100.0" stroke="TRANSPARENT" strokeType="INSIDE" />
          <Circle id="cShapeGreen" fx:id="cShapeBlue" fill="$x1" layoutX="300.0" layoutY="200.0" radius="100.0" stroke="TRANSPARENT" strokeType="INSIDE" />
          <Circle fx:id="cRed" onMouseEntered="#handleOnMouseEntered" onMouseExited="#handleOnMouseExited" radius="50.0" stroke="BLACK" strokeType="INSIDE">
            <fill>
              <Color blue="0.400" green="0.400" red="1.000" fx:id="x2" />
            </fill>
          </Circle>
          <Circle fx:id="cViolett" fill="#d633ff" onMouseEntered="#handleOnMouseEntered" onMouseExited="#handleOnMouseExited" radius="50.0" stroke="BLACK" strokeType="INSIDE" />
          <Circle fx:id="cGreen" fill="#33ff54" onMouseEntered="#handleOnMouseEntered" onMouseExited="#handleOnMouseExited" radius="50.0" stroke="BLACK" strokeType="INSIDE" />
          <Circle fx:id="cYellow" fill="#fff733" onMouseEntered="#handleOnMouseEntered" onMouseExited="#handleOnMouseExited" radius="50.0" stroke="BLACK" strokeType="INSIDE" />
          <Circle fx:id="cBlue" fill="#7266ff" onMouseEntered="#handleOnMouseEntered" onMouseExited="#handleOnMouseExited" radius="50.0" stroke="BLACK" strokeType="INSIDE" />
        </children>
      </AnchorPane>
      /*
       * To change this template, choose Tools | Templates
       * and open the template in the editor.
       */
      package xjavafxapplication14;
      
      import java.net.URL;
      import java.util.ResourceBundle;
      import javafx.animation.Animation.Status;
      import javafx.animation.Interpolator;
      import javafx.animation.ParallelTransition;
      import javafx.animation.ParallelTransitionBuilder;
      import javafx.animation.PathTransition;
      import javafx.animation.PathTransitionBuilder;
      import javafx.animation.Timeline;
      import javafx.beans.property.DoubleProperty;
      import javafx.beans.property.ObjectProperty;
      import javafx.beans.property.SimpleDoubleProperty;
      import javafx.beans.property.SimpleObjectProperty;
      import javafx.fxml.FXML;
      import javafx.fxml.Initializable;
      import javafx.scene.input.MouseEvent;
      import javafx.scene.layout.AnchorPane;
      import javafx.scene.paint.Color;
      import javafx.scene.shape.Circle;
      import javafx.util.Duration;
      
      /**
       *
       * @author PRo
       */
      public class SampleController implements Initializable {
          
          @FXML private AnchorPane root = null;
          
          @FXML private Circle cShapeRed = null;
          @FXML private Circle cShapeViolett = null;
          @FXML private Circle cShapeGreen = null;
          @FXML private Circle cShapeYellow = null;
          @FXML private Circle cShapeBlue = null;
          @FXML private Circle cRed = null;
          @FXML private Circle cViolett = null;
          @FXML private Circle cGreen = null;
          @FXML private Circle cYellow = null;
          @FXML private Circle cBlue = null;
          
          private Duration currentTime = null;
          private DoubleProperty dpDuration = null;
          private ObjectProperty<Duration> opRed = null;
          private ObjectProperty<Duration> opViolett = null;
          private ObjectProperty<Duration> opGreen = null;
          private ObjectProperty<Duration> opYellow = null;
          private ObjectProperty<Duration> opBlue = null;
          private ParallelTransition parallelTransition = null;
          
          @Override
          public void initialize(URL url, ResourceBundle rb) {
              cShapeRed.setRotate(-90.0d);
              cShapeYellow.setRotate(-18.0d);
              cShapeViolett.setRotate(54.0d);
              cShapeBlue.setRotate(126.0d);
              cShapeGreen.setRotate(198.0d);
              
              opRed = new SimpleObjectProperty<>(Duration.seconds(50.0d));
              opViolett = new SimpleObjectProperty<>(Duration.seconds(50.0d));
              opGreen = new SimpleObjectProperty<>(Duration.seconds(50.0d));
              opYellow = new SimpleObjectProperty<>(Duration.seconds(50.0d));
              opBlue = new SimpleObjectProperty<>(Duration.seconds(50.0d));
              
              dpDuration = new SimpleDoubleProperty(50.0d);
              parallelTransition = ParallelTransitionBuilder
                      .create()
                      .children(
                          this.createPathTransition(cShapeRed, cRed, opRed),
                          this.createPathTransition(cShapeYellow, cYellow, opYellow),
                          this.createPathTransition(cShapeViolett, cViolett, opViolett),
                          this.createPathTransition(cShapeBlue, cBlue, opBlue),
                          this.createPathTransition(cShapeGreen, cGreen, opGreen)
                      )
                      .cycleCount(Timeline.INDEFINITE)
                      .build();
              parallelTransition.playFromStart();
          }
          
          private PathTransition createPathTransition(
                  Circle path, Circle node,
                  ObjectProperty<Duration> op
          ) {
              PathTransition pt = PathTransitionBuilder.create()
                              .cycleCount(Timeline.INDEFINITE)
                              .duration(op.getValue())
                              .interpolator(Interpolator.LINEAR)
                              .node(node)
                              .path(path)
                              .build();
              pt.durationProperty().bind(op);
              return pt;
          }
          
          @FXML private void handleOnMouseEntered(MouseEvent me) {
              if (parallelTransition.getStatus().equals(Status.RUNNING)) {
                  currentTime = parallelTransition.getCurrentTime();
                  parallelTransition.stop();
                  
                  Circle circle = (Circle) me.getSource();
                  cShapeRed.setFill(circle.getFill());
                  
                  double seconds = opRed.getValue().toSeconds() - 3;
                  if (seconds < 2.0d) {
                      seconds = 2.0d;
                  }
      System.out.println("duration: " + seconds);
                  opRed.setValue(Duration.seconds(seconds));
                  opViolett.setValue(Duration.seconds(seconds));
                  opGreen.setValue(Duration.seconds(seconds));
                  opYellow.setValue(Duration.seconds(seconds));
                  opBlue.setValue(Duration.seconds(seconds));
              }
          }
          
          @FXML private void handleOnMouseExited(MouseEvent me) {
              if (parallelTransition.getStatus().equals(Status.STOPPED)) {
                  parallelTransition.playFrom(currentTime);
                  
                  cShapeRed.setFill(Color.TRANSPARENT);
              }
          }
      }
      Thanks
      Peter
        • 1. Re: Start, stop a ParallelTransition with changed Duration in PathTransition
          James_D
          Instead of manipulating the duration of the animation, try manipulating the rate. I think this will do what you need.
          • 2. Re: Start, stop a ParallelTransition with changed Duration in PathTransition
            James_D
            import java.net.URL;
            import java.util.ResourceBundle;
            import javafx.animation.Animation.Status;
            import javafx.animation.Interpolator;
            import javafx.animation.ParallelTransition;
            import javafx.animation.ParallelTransitionBuilder;
            import javafx.animation.PathTransition;
            import javafx.animation.PathTransitionBuilder;
            import javafx.animation.Timeline;
            import javafx.beans.property.DoubleProperty;
            import javafx.beans.property.ObjectProperty;
            import javafx.beans.property.SimpleDoubleProperty;
            import javafx.beans.property.SimpleObjectProperty;
            import javafx.fxml.FXML;
            import javafx.fxml.Initializable;
            import javafx.scene.input.MouseEvent;
            import javafx.scene.layout.AnchorPane;
            import javafx.scene.paint.Color;
            import javafx.scene.shape.Circle;
            import javafx.util.Duration;
            
            /**
             * 
             * @author PRo
             */
            public class SampleController implements Initializable {
            
              @FXML
              private AnchorPane root = null;
            
              @FXML
              private Circle cShapeRed = null;
              @FXML
              private Circle cShapeViolett = null;
              @FXML
              private Circle cShapeGreen = null;
              @FXML
              private Circle cShapeYellow = null;
              @FXML
              private Circle cShapeBlue = null;
              @FXML
              private Circle cRed = null;
              @FXML
              private Circle cViolett = null;
              @FXML
              private Circle cGreen = null;
              @FXML
              private Circle cYellow = null;
              @FXML
              private Circle cBlue = null;
            
              private Duration currentTime = null;
              private DoubleProperty dpDuration = null;
              private ObjectProperty<Duration> opRed = null;
              private ObjectProperty<Duration> opViolett = null;
              private ObjectProperty<Duration> opGreen = null;
              private ObjectProperty<Duration> opYellow = null;
              private ObjectProperty<Duration> opBlue = null;
              private ParallelTransition parallelTransition = null;
            
              private static final double INITIAL_DURATION = 50;
              private double currentRate = 1;
            
              @Override
              public void initialize(URL url, ResourceBundle rb) {
                cShapeRed.setRotate(-90.0d);
                cShapeYellow.setRotate(-18.0d);
                cShapeViolett.setRotate(54.0d);
                cShapeBlue.setRotate(126.0d);
                cShapeGreen.setRotate(198.0d);
            
                opRed = new SimpleObjectProperty(Duration.seconds(INITIAL_DURATION));
                opViolett = new SimpleObjectProperty(Duration.seconds(INITIAL_DURATION));
                opGreen = new SimpleObjectProperty(Duration.seconds(INITIAL_DURATION));
                opYellow = new SimpleObjectProperty(Duration.seconds(INITIAL_DURATION));
                opBlue = new SimpleObjectProperty(Duration.seconds(INITIAL_DURATION));
            
                dpDuration = new SimpleDoubleProperty(50.0d);
                parallelTransition = ParallelTransitionBuilder
                    .create()
                    .children(this.createPathTransition(cShapeRed, cRed, opRed),
                        this.createPathTransition(cShapeYellow, cYellow, opYellow),
                        this.createPathTransition(cShapeViolett, cViolett, opViolett),
                        this.createPathTransition(cShapeBlue, cBlue, opBlue),
                        this.createPathTransition(cShapeGreen, cGreen, opGreen))
                    .cycleCount(Timeline.INDEFINITE).build();
                parallelTransition.playFromStart();
              }
            
              private PathTransition createPathTransition(Circle path, Circle node,
                  ObjectProperty<Duration> op) {
                PathTransition pt = PathTransitionBuilder.create()
                    .cycleCount(Timeline.INDEFINITE).duration(op.getValue())
                    .interpolator(Interpolator.LINEAR).node(node).path(path).build();
                pt.durationProperty().bind(op);
                return pt;
              }
            
              @FXML
              private void handleOnMouseEntered(MouseEvent me) {
                if (parallelTransition.getStatus().equals(Status.RUNNING)) {
                  currentTime = parallelTransition.getCurrentTime();
                  parallelTransition.stop();
                  parallelTransition.setRate(0);
            
                  Circle circle = (Circle) me.getSource();
                  cShapeRed.setFill(circle.getFill());
            
                  currentRate = INITIAL_DURATION / ((INITIAL_DURATION / currentRate) - 3);
                  if (currentRate > 25 || currentRate < 0) {
                    currentRate = 25;
                  }
            
                }
              }
            
              @FXML
              private void handleOnMouseExited(MouseEvent me) {
                if (parallelTransition.getRate() == 0) {
                  parallelTransition.setRate(currentRate);
                  parallelTransition.playFrom(currentTime);
                  cShapeRed.setFill(Color.TRANSPARENT);
                }
              }
            }