silversunhunter silversunhunter - 10 months ago 48
Java Question

JavaFX Concurrency: Can I run an objects method in a task?

If I have a class with methods:

class Car{
private String engineRPM;

public Car(){}

public String idleEngine(){
if (engineOn()){
engineRPM = getEngineRPM();
}
return engineRPM;
}
}


How do I run the method in a task on a background thread in Main and then take its returned value and update the GUI?

public class Main extends Application {

Car myCar;

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

}

@Override
public void start(Stage primaryStage) throws Exception{
FXMLLoader loader = new FXMLLoader(getClass().getResource("fxml/entry.fxml"));
Parent root = loader.load();
this.mainController = (SystemMessage) loader.getController();
primaryStage.setTitle("Car");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();

//perform background task of class method here
myCar = new Car();
myCar.startEngine();
String RPM = myCar.engineIdle(); //
this.mainController.postMessage(RPM);

}

Answer Source

The basic idea is

  • Create a Task whose call() method does whatever you need to do in the background thread
  • If you have something to execute on the FX Application Thread when the task finishes, use the onSucceeded handler, which is invoked (on the FX Application Thread) after the call() method completes
  • When the call() method finishes, whatever is returned from it is set as the task's value, so you can call getValue() to see what was returned
  • Create a thread from the task, and call start() to execute it

So in your case, this just looks like

public class Main extends Application {


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

    }

    @Override
    public void start(Stage primaryStage) throws Exception{
        FXMLLoader loader = new FXMLLoader(getClass().getResource("fxml/entry.fxml"));
        Parent root = loader.load();
        SystemMessage mainController = loader.getController();
        primaryStage.setTitle("Car");
        primaryStage.setScene(new Scene(root, 300, 275));
        primaryStage.show();

        Task<String> carTask = new Task<String>() {
            @Override
            protected String call() throws Exception {
                Car myCar = new Car();
                myCar.startEngine();
                return myCar.engineIdle();
            }
        };
        carTask.setOnSucceeded(e -> mainController.postMessage(carTask.getValue()));
        new Thread(carTask).start();

    }

}

See the documentation for Task: it has plenty of examples.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download