This discussion is archived
2 Replies Latest reply: Jan 22, 2013 3:47 PM by James_D RSS

Start, stop a ParallelTransition with changed Duration in PathTransition

875316 Newbie
Currently Being Moderated
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 Guru
    Currently Being Moderated
    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 Guru
    Currently Being Moderated
    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);
        }
      }
    }

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points