I’m trying to make a chronometer program using java FXML in Scene Builder and I can’t

Asked

Viewed 18 times

-2

Every time I click the button, in an attempt to start the chronometer, this error happens:

Exception in thread "Thread-4" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4

referring to that code line : `

lblMainChronometer.setText(String.format("%02d:%02d:%02d.%02d", hours, minutes, seconds, secondsHundredth));

This is the Fxmldcumentcontroler of my program :

package chronometer;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;

public class FXMLDocumentController implements Initializable {
    
    @FXML    
    private Label lblMainChronometer;

    private static int startTime;
    
    private void startCounter() { startTime = (int) System.currentTimeMillis(); }
    
    private static int currentTimeHundredth() {
        double currentTimeMillis;
        currentTimeMillis = startTime - System.currentTimeMillis();
        int currentTimeHundreth = (int) Math.floor(currentTimeMillis / 10);
        return currentTimeHundreth; 
    }
    
    private Runnable mainChronometer = new Runnable() {
        @Override
        public void run() {
            while (true) {
                
                int secondsHundredth = currentTimeHundredth() % 100;
                int currentTimeSeconds = currentTimeHundredth() - secondsHundredth;
                int seconds = (int) (currentTimeSeconds % 60);
                int minutes = (int) (currentTimeSeconds / 60);
                minutes %= 60; // to stay just the minutes (excluding the hours)           
                int hours = (int) (minutes / 60);
                lblMainChronometer.setText(String.format("%02d:%02d:%02d.%02d", hours, minutes, seconds, secondsHundredth));
                
            }
        }
    };
          
    @FXML
    private void handleButtonAction(ActionEvent event) throws InterruptedException {
        
        startCounter();
        new Thread(mainChronometer).start();
    }
    
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        
    }    
    
}

Help me out, please!!!

1 answer

0

You are trying to update the Javafx thread using another Thread, this is not possible. Javafx only accepts things from within its own thread.

Try using Platform.runLater() and pass as a runnable parameter with the command to update the value in Javafx.

I advise you to search for the Task class in: Docs.oracle.com/javase/8/javafx/api/javafx/Concurrent/Task.html. may be that the updateValue() method is useful to you because it returns partial results, which would serve you to update the information on the screen. In this link I gave you there is an example of code that I think will serve you well.

Example:

public void handleClick() {
        // Verificar se esta thread já esta rodando.
        if (!isRunning) {
            Task<String> task = new Task<String>() {
                @Override
                protected String call() throws Exception {
                    isRunning = true;
                    String a = null;
                    for (int i = 0; i <= 60; i++) {
                        String finalA = String.valueOf(i);

                        //  Colocar a variável na sua label através da JavaFX Thread.
                        Platform.runLater(() -> {
                            label.setText(finalA);
                        });
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {

                        }
                    }
                    isRunning = false;
                    return a;
                }

            };
            new Thread(task).start();
        }
    }

This is a way that might work for your case.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.