user6857832
user6857832

Reputation:

How can I update random value of radius after every cycle?

Here is my following code:

 public void start(Stage primaryStage) throws Exception {
        Pane root = new Pane();
        Scene scene = new Scene(root, 500, 600);
        Random rand = new Random();

       int random = rand.nextInt(100-5)+5;
       Circle circle = new Circle(0, 10, random);
       circle.setFill(Color.RED);
       root.getChildren().add(circle);

       Timeline timeline = new Timeline(
            new KeyFrame(
              Duration.seconds(2),
              new KeyValue(circle.translateXProperty(), 600)
         ));
        timeline.setCycleCount(Animation.INDEFINITE);
        timeline.setAutoReverse(false);
        timeline.play();

        primaryStage.setScene(scene);
        primaryStage.show();

    }

In this code it only update the random value once, but I want it to update random value after each cycle. Is there any way I can update my random value after each cycle? Any help is appreciated!

Upvotes: 3

Views: 125

Answers (6)

fabian
fabian

Reputation: 82461

Add a EventHandler<ActionEvent> that updates the radius property to the last KeyFrame of the Timeline:

final Random rand = new Random();

int random = rand.nextInt(100-5)+5;
final Circle circle = new Circle(0, 10, random);
circle.setFill(Color.RED);
root.getChildren().add(circle);

Timeline timeline = new Timeline(
    new KeyFrame(
      Duration.seconds(2),
      event -> circle.setRadius(rand.nextInt(100-5)+5),
      new KeyValue(circle.translateXProperty(), 600)
 ));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.setAutoReverse(false);
timeline.play();

Upvotes: 0

ItachiUchiha
ItachiUchiha

Reputation: 36722

The default Interpolater(EASE_BOTH) clamps the value of time for current interval i.e. frac value will range from [0.0, ... , 1.0]. You can use the same information and update the radius at the beginning of the new cycle.

public void start(Stage primaryStage) {
    Pane root = new Pane();
    Scene scene = new Scene(root, 500, 600);

    final Random random = new Random();
    Circle circle = new Circle(0, 0, random.nextInt(100));
    circle.setFill(Color.RED);
    root.getChildren().add(circle);

    Animation animation = new Transition() {
        {
            setCycleCount(INDEFINITE);
            setCycleDuration(Duration.seconds(2));
        }

        @Override
        protected void interpolate(double frac) {
            if (frac == 0) {
                final int newRadius = random.nextInt(100);
                System.out.println("New Radius: " + newRadius);
                circle.setRadius(newRadius + 5);
            }
            circle.setTranslateX(frac * 600);
        }
    };
    animation.play();
    primaryStage.setScene(scene);
    primaryStage.show();
}

Upvotes: 1

Jenna Sloan
Jenna Sloan

Reputation: 382

You should add a EventHandler<ActionEvent> to your call to the KeyValue constructor.

That is, add a parameter to new KeyValue(circle.translateXProperty(), 600) so it looks something like new KeyValue(circle.translateXProperty(), (event)->{circle.setRadius(rand.nextInt(100-5)+5);}, 600)

Upvotes: 1

Zsolt V
Zsolt V

Reputation: 517

There is a constructor for Keyframe which takes multiple KeyValue. You can add to the constructor a new KeyValue with the radius of circle. As far as I can see you should create your own implementation of Interpolator to make alive the random behaviour for the radius. (Maybe there are third party solutions for that)

Upvotes: 1

Naman
Naman

Reputation: 31878

If you're using the Timeline

It is not possible to change the keyFrames of a running Timeline. If the value of keyFrames is changed for a running Timeline, it has to be stopped and started again to pick up the new value.

So, you can recreate the timeline everytime you want to create a new keyFrame, in your case with a new Circle(0, 10, new Random().nextInt(100-5)+5, Color.RED);

Upvotes: 1

Sondering Narcissist
Sondering Narcissist

Reputation: 419

Not sure if this will slow down your code, but you might want to try setting cycle count to 1 instead of Animation.INDEFINITE and wrapping the entire block in a while loop:

public void start(Stage primaryStage) throws Exception {
    Pane root = new Pane();
    Scene scene = new Scene(root, 500, 600);
    Random rand = new Random();

    primaryStage.setScene(scene);
    primaryStage.show();

    while (true) { 
        int random = rand.nextInt(100-5)+5;
        Circle circle = new Circle(0, 10, random);
        circle.setFill(Color.RED);
        root.getChildren().add(circle);

        Timeline timeline = new Timeline(new KeyFrame(
            Duration.seconds(2),
            new KeyValue(circle.translateXProperty(), 600)
        ));
        timeline.setCycleCount(1);
        timeline.setAutoReverse(false);

        timeline.play();
    }
}

One issue is that the primaryStage.show() will get moved up (so that it still runs despite the forever loop). Consider changing the while (true) to something else if this becomes a problem.

Upvotes: 0

Related Questions