Lalit Chattar
Lalit Chattar

Reputation: 1984

JavaFX pass values from child to parent

I have one parent controller which contain one button. When I click on button it open new window and show some data into table. The code I have used for opening window is

            Stage stage = new Stage();
            FXMLLoader fxmlLoader = new FXMLLoader(
                    getClass().getResource("../layout/SearchCustomer.fxml"));
            Parent parent = (Parent) fxmlLoader.load();
            Scene scene = new Scene(parent);
            stage.initModality(Modality.APPLICATION_MODAL);
            stage.initOwner(parent.getScene().getWindow());
            stage.setScene(scene);
            stage.resizableProperty().setValue(false);
            stage.showAndWait();

It opens window properly. Now what I need is, when I double click on the row of table of the child window, It should set some value in parent controller textbox. How would we pass this value from child controller to parent controller?

Upvotes: 3

Views: 6357

Answers (2)

Howard J
Howard J

Reputation: 421

In my example below, the account window (child/dialog) passes the newly selected account name back to the parent window when the save button is clicked. On the parent window ...

Stage nstage = new Stage();
                FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Accounts.fxml"));
                Parent root = (Parent) fxmlLoader.load();
                AccountsController accController = fxmlLoader.getController();
                accController.dialogMode(); //Call a function in acconunt windoow to preset some fields

                Scene scene = new Scene(root);
                nstage.setTitle("Create Company Account");
                nstage.setScene(scene);

                Stage stage  = (Stage) src.getScene().getWindow();
                nstage.initOwner(stage);
                nstage.initModality(Modality.APPLICATION_MODAL);
                //nstage.initStyle(StageStyle.UNDECORATED); 
                nstage.show();

                nstage.setOnCloseRequest(new EventHandler<WindowEvent>(){
                    public void handle(WindowEvent we) {
                            txtCompany.setText( accController.lbl1.getText() );
                    }

                });

Upvotes: 0

James_D
James_D

Reputation: 209225

Expose a property in your child controller and observe it from the "parent" controller. There isn't really enough information in your question to give a precise answer, but it would look something like:

public class ChildController {

    @FXML
    private TableView<Customer> customerTable ;

    private final ReadOnlyObjectWrapper<Customer> currentCustomer = new ReadOnlyObjectWrapper<>();

    public ReadOnlyObjectProperty<Customer> currentCustomerProperty() {
        return currentCustomer.getReadOnlyProperty() ;
    }

    public Customer getCurrentCustomer() {
        return currentCustomer.get();
    }

    public void initialize() {
        // set up double click on table:

        customerTable.setRowFactory(tv -> {
            TableRow<Customer> row = new TableRow<>();
            row.setOnMouseClicked(e -> {
                if (row.getClickCount() == 2 && ! row.isEmpty()) {
                    currentCustomer.set(row.getItem());
                }
            }
        });

    }
}

and then you just do:

Stage stage = new Stage();
FXMLLoader fxmlLoader = new FXMLLoader(
        getClass().getResource("../layout/SearchCustomer.fxml"));
Parent parent = (Parent) fxmlLoader.load();

ChildController childController = fxmlLoader.getController();
childController.currentCustomerProperty().addListener((obs, oldCustomer, newCustomer) -> {
    // do whatever you need with newCustomer....
});

Scene scene = new Scene(parent);
stage.initModality(Modality.APPLICATION_MODAL);
stage.initOwner(parent.getScene().getWindow());
stage.setScene(scene);
stage.resizableProperty().setValue(false);
stage.showAndWait();

An alternative approach is to use a Consumer as a callback in the child controller:

public class ChildController {

    @FXML
    private TableView<Customer> customerTable ;

    private Consumer<Customer> customerSelectCallback ;

    public void setCustomerSelectCallback(Consumer<Customer> callback) {
        this.customerSelectCallback = callback ;
    }

    public void initialize() {
        // set up double click on table:

        customerTable.setRowFactory(tv -> {
            TableRow<Customer> row = new TableRow<>();
            row.setOnMouseClicked(e -> {
                if (row.getClickCount() == 2 && ! row.isEmpty()) {
                    if (customerSelectCallback != null) {
                        customerSelectCallback.accept(row.getItem());
                    }
                }
            }
        });

    }
}

And in this version you do

Stage stage = new Stage();
FXMLLoader fxmlLoader = new FXMLLoader(
        getClass().getResource("../layout/SearchCustomer.fxml"));
Parent parent = (Parent) fxmlLoader.load();

ChildController childController = fxmlLoader.getController();
childController.setCustomerSelectCallback(customer -> {
    // do whatever you need with customer....
});

Scene scene = new Scene(parent);
stage.initModality(Modality.APPLICATION_MODAL);
stage.initOwner(parent.getScene().getWindow());
stage.setScene(scene);
stage.resizableProperty().setValue(false);
stage.showAndWait();

Upvotes: 12

Related Questions