ashah
ashah

Reputation: 177

How to wait in Java FX controller for return value from window?

I have an java fx controller class having do method, where I wish to wait till I collect information from another screen. See below code to understand better. This do() method is called from my Javafx Application class's start() method.

@FXML
public void do() throws Exception {

    FXMLLoader fxmlLoader = new FXMLLoader(this.getClass().getResource("/fxml/myPage.fxml"));
    Parent root = (Parent)fxmlLoader.load();
    Scene mainScene = new Scene(root);
    Stage stage = new Stage();  
    stage.setHeight(500);
    stage.setWidth(400);
    stage.setScene(mainScene);
    stage.setTitle("Provide input");        
    stage.show();       
    System.out.println(Thread.currentThread().getName() +"returned");
}

So here I am calling do method from my Application and wish that do() return me value that I capture from myPage screen. Here I don't find anyway to wait. If I put wait after call to show(), screen is never displayed. JavaFX expect that I return from this function and then only I see screen and I also see "Returned" message on console.

I can write another method which controller of this new page will call after fetching input but then I am anyway returning from my do() method. How can I stay here only? I tried to open new Thread and then load fxml but it gives "Not Same Thread" error. I see that even start() method of javaFX Application class need to get control back to show the screen.

Upvotes: 0

Views: 2491

Answers (1)

James_D
James_D

Reputation: 209330

You can either use stage.showAndWait() which will basically do what it says on the box: show the stage and block execution until the stage is hidden:

@FXML
public void do() throws Exception {

    FXMLLoader fxmlLoader = new FXMLLoader(this.getClass().getResource("/fxml/myPage.fxml"));
    Parent root = (Parent)fxmlLoader.load();
    Scene mainScene = new Scene(root);
    Stage stage = new Stage();  
    stage.setHeight(500);
    stage.setWidth(400);
    stage.setScene(mainScene);
    stage.setTitle("Provide input");        
    stage.showAndWait();     
    // get results of input here...  
    System.out.println(Thread.currentThread().getName() +"returned");
}

or you can register a listener that is invoked when the stage is hidden, and process the input in it:

@FXML
public void do() throws Exception {

    FXMLLoader fxmlLoader = new FXMLLoader(this.getClass().getResource("/fxml/myPage.fxml"));
    Parent root = (Parent)fxmlLoader.load();
    Scene mainScene = new Scene(root);
    Stage stage = new Stage();  
    stage.setHeight(500);
    stage.setWidth(400);
    stage.setScene(mainScene);
    stage.setTitle("Provide input");   
    stage.setOnHidden(e -> {
        // process input here...
    });     
    stage.show();       
    System.out.println(Thread.currentThread().getName() +"returned");
}

This version will not block execution, so your do() method will exit immediately, but the code block in the handler will be invoked when the new stage hides.

Upvotes: 1

Related Questions