Search code examples
javamultithreadingjavafxjavafx-bindings

Timer in JavaFX updating Label (Bindings)


I want to add a clock to my application that tells how long you have been doing the task. To simplify it, I have included a counter that increments every second in a new thread and update the label 'setTimer' with the counter number. For this I have a label fx:id="setTimer" in my .fxml file and imported it into my class.

 @FXML
    private Label setTimer;

And created another class in my class that extends the thread TimerTask and increments the counter by one on each call. Created a new Object 'text', which should always be updated with the current value of the counter.

    SimpleStringProperty text = new SimpleStringProperty("undefined");
public class MyTask extends TimerTask {
        @Override
        public void run() {
            counter++;
            text.set(Integer.toString(counter));
        }
    }

To have this class called every second I created a timer in the initialize method and set it to one second.

@Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        MyTask myTask = new MyTask();
        Timer timer = new Timer(true);
        timer.scheduleAtFixedRate(myTask, 0 , 1000);
        setTimer.textProperty().bind(text);
    }

At the moment I get the exception 'Not on FX application thread; currentThread = Timer-0'.

I've tried many ways to solve my problem, but I haven't gotten to the right point. My idea of ​​what I want to do should be clear, and I would be happy if someone could help me. My Problem is to update the changes of the counter in the GUI. It doesn't have to be solved the way I thought it would, just need a tip on how to best implement it.

Thank you


Solution

  • Ok, my comments are too long. This is how I would try to do it.

    1. Start the stopwatch on the application being loaded
    2. Create a new thread that launches itself every so often.
    3. Inside there, get the time from the Stopwatch in seconds (sw.getTime(TimeUntis.seconds)). Convert that to hours and minutes if you want like shown in this SO post
    4. Then, write the time to the UI using Platform.runLater(new Runnable(){ /* access ui element and write time here */ });