Carl Turland
Carl Turland

Reputation: 61

JavaFX Simple Update Label (Threading)

I'm trying to demonstrate to a few beginner programmers how to set a label on a JavaFX app to auto update. Basically they would like the value to decrease every minute or so on the label without any user interaction.

Java isn't my strong point and looking through some previous questions I get that I need to deal with threads and Runnable().

I have put the code together below that works, but I was just wondering if there is a better way of doing this or an easier way to demonstrate the same outcome with simpler code.

public class MainTimer2 extends Application {
    private int count = 100;
    private Label response = new Label(Integer.toString(count));

    public static void main(String[] args) {
        launch(args);
    }

    //Update function
    private void decrementCount() {
        count--;
        response.setText(Integer.toString(count));
    }

    @Override
    public void start(Stage myStage) {
        myStage.setTitle("Update Demo");

        //Vertical and horizontal gaps set to 10px
        FlowPane rootNode = new FlowPane(10, 10);

        rootNode.setAlignment(Pos.CENTER);

        Scene myScene = new Scene(rootNode, 200, 100);

        myStage.setScene(myScene);

        Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {
                Runnable updater = new Runnable() {

                    @Override
                    public void run() {
                        decrementCount();
                    }
                };
                while (true) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException ex) {
                        System.out.println("Timer error");
                    }
                    // UI update is run on the Application thread
                    Platform.runLater(updater);
                }
            }
        });
        // don't let thread prevent JVM shutdown
        thread.setDaemon(true);
        thread.start();
        rootNode.getChildren().addAll(response);
        myStage.show();
    }
}

Upvotes: 1

Views: 979

Answers (1)

c0der
c0der

Reputation: 18792

Count down by using PauseTransition:

import javafx.animation.PauseTransition;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
import javafx.util.Duration;

public class MainTimer2 extends Application {

    private int count = 100;
    private Label response = new Label(Integer.toString(count));

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage myStage) {
        myStage.setTitle("Update Demo");

        //Vertical and horizontal gaps set to 10px
        FlowPane rootNode = new FlowPane(10, 10);
        rootNode.setAlignment(Pos.CENTER);

        Scene myScene = new Scene(rootNode, 200, 100);
        myStage.setScene(myScene);

        rootNode.getChildren().addAll(response);
        myStage.show();
        update();
    }

    private void update() {

        PauseTransition pause = new PauseTransition(Duration.seconds(1));
        pause.setOnFinished(event ->{
            decrementCount();
            pause.play();
        });
        pause.play();
    }

    //Update function
    private void decrementCount() {
        count = (count > 0) ? count -1 : 100;
        response.setText(Integer.toString(count));
    }
}

Alternatively you could use Timeline:

    private void update() {

        KeyFrame keyFrame = new KeyFrame(
                Duration.seconds(1),
                event -> {
                    decrementCount();
                }
        );
        Timeline timeline = new Timeline();
        timeline.setCycleCount(Animation.INDEFINITE);
        //if you want to limit the number of cycles use 
        //timeline.setCycleCount(100);
        timeline.getKeyFrames().add(keyFrame);
        timeline.play();
    }

Upvotes: 3

Related Questions