jaaBeg16
jaaBeg16

Reputation: 23

JavaFX animation stops after first cycle

I want a counter that counts till 3, and after that it should restart at 0 and repeat counts up until 3 indefinitely. But when my counter reaches 3, last thing my programm does is setting the text "0". I think I'm not using animation correctly. I hope someone knows what I do wrong. Note that this is just a simplification of my real problem; there might be easier ways to count until 3...

import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline; 
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.text.Font;
import javafx.scene.text.FontPosture;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;

public class GeneralTesting extends Application{
    private Text text;
    private int counter = 1;
    public static void main(String[] args) {
        launch();
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Pane pane = new Pane();

        text = new Text(500, 300, "0");

        text.setFont(Font.font("Comic Sans MS", FontWeight.BOLD, FontPosture.REGULAR, 100));

        Animation animation = new Timeline(new KeyFrame(Duration.millis(1000), e -> {changeText(counter++);}));
        animation.setCycleCount(Timeline.INDEFINITE);
        animation.play();

        pane.getChildren().addAll(text);

        Scene scene = new Scene(pane);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public void changeText(int counter){
        if (counter > 5){
            counter = 0;
        }
        text.setText(String.valueOf(counter));
    }

}

Upvotes: 0

Views: 488

Answers (2)

James_D
James_D

Reputation: 209684

In

if (counter > 5) {
    counter = 0 ;
}

you are resetting the local variable counter to 0. The instance field remains at its previous value. Consequently, on the next iteration of the timeline, it is still greater than 5 and you set the local variable to zero again.

Remove the local variable entirely, and just update the field:

import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline; 
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.text.Font;
import javafx.scene.text.FontPosture;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;

public class GeneralTesting extends Application{
    private Text text;
    private int counter = 1;
    public static void main(String[] args) {
        launch();
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Pane pane = new Pane();

        text = new Text(500, 300, "0");

        text.setFont(Font.font("Comic Sans MS", FontWeight.BOLD, FontPosture.REGULAR, 100));

        Animation animation = new Timeline(new KeyFrame(Duration.millis(1000), e -> {
            counter++; 
            changeText();
        }));

        animation.setCycleCount(Timeline.INDEFINITE);
        animation.play();

        pane.getChildren().addAll(text);

        Scene scene = new Scene(pane);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public void changeText(){
        if (counter > 5){
            counter = 0;
        }
        text.setText(String.valueOf(counter));
    }

}

Better still, use an IntegerProperty and bind the text to its value:

import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline; 
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.text.Font;
import javafx.scene.text.FontPosture;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;

public class GeneralTesting extends Application{
    private Text text;
    public static void main(String[] args) {
        launch();
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Pane pane = new Pane();

        text = new Text(500, 300, "0");

        text.setFont(Font.font("Comic Sans MS", FontWeight.BOLD, FontPosture.REGULAR, 100));

        IntegerProperty counter = new SimpleIntegerProperty(1);
        text.textProperty().bind(counter.asString());

        Animation animation = new Timeline(new KeyFrame(Duration.millis(1000), 
            e -> counter.set((counter.get()+1) % 5)));

        animation.setCycleCount(Timeline.INDEFINITE);
        animation.play();

        pane.getChildren().addAll(text);

        Scene scene = new Scene(pane);
        primaryStage.setScene(scene);
        primaryStage.show();
    }


}

Upvotes: 2

SedJ601
SedJ601

Reputation: 13859

One way is to use mod to keep the range from 0 to 3.

    Pane pane = new Pane();

    Text text = new Text(500, 300, "0");
    int[] counter =
    {
        0
    };
    text.setFont(Font.font("Comic Sans MS", FontWeight.BOLD, FontPosture.REGULAR, 100));

    Animation animation = new Timeline(new KeyFrame(Duration.millis(1000), e
            ->
    {
        text.setText(Integer.toString(counter[0]++ % 4));
    }));
    animation.setCycleCount(Timeline.INDEFINITE);
    animation.play();

    pane.getChildren().addAll(text);

    Scene scene = new Scene(pane);
    primaryStage.setScene(scene);
    primaryStage.show();

Upvotes: 0

Related Questions