scott
scott

Reputation: 27

How to use Timeline to perform a void method every x seconds on JavaFX?

The problem:

I'm trying to use Timeline to call a void method action() every 0.5 seconds. I have researched how to do this and looked at similar questions on this site, but none are working out for me.

What I have tried #1:

Duration sec = Duration.ofSeconds((long) 0.5);
this.timeline = new Timeline(new KeyFrame(sec, e -> {
    action();
}));

The error the above caused: "The constructor KeyFrame(Duration, ( e) -> {}) is undefined".

What I have tried #2:

this.timeline = new Timeline(new KeyFrame(Duration.ofSeconds((long) 0.5), new EventHandler<ActionEvent>() 
        {

            @Override
            public void handle(ActionEvent event) {
                action();
            }
            }));

The error the above caused: "The constructor KeyFrame(Duration, new EventHandler(){}) is undefined".

Thanks in advance for any help.

Upvotes: 1

Views: 2662

Answers (1)

Slaw
Slaw

Reputation: 45786

Based on this line:

Duration sec = Duration.ofSeconds((long) 0.5);

Note: Casting 0.5 to a long will simply give you 0.

You are using the wrong Duration class. The above indicates you're using java.time.Duration when you need to be using javafx.util.Duration. Remove the import statement for the former and replace it with one for the latter. Then change the above line to:

Duration sec = Duration.seconds(0.5);

Notice the static method for the JavaFX Duration class is named seconds, not ofSeconds. Also, if you want the Timeline to repeatedly call your method every 0.5 seconds then you need to set its cycle count to Animation#INDEFINITE.

Here's an example:

import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Duration;

public class App extends Application {

  private Label label;
  private int count;

  @Override
  public void start(Stage primaryStage) {
    label = new Label();

    Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(0.5), e -> incrementLabel()));
    timeline.setCycleCount(Animation.INDEFINITE);
    timeline.playFromStart();

    primaryStage.setScene(new Scene(new StackPane(label), 500, 300));
    primaryStage.show();
  }

  private void incrementLabel() {
    label.setText(String.format("%,d", count++));
  }
}

Note: "Incrementing" the text of the Label could be done directly in the EventHandler, but I moved it to a void method to better fit your question.

Upvotes: 4

Related Questions