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