Reputation:
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
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
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
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
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
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
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