3

I have a parent Window which displays people i.e:

FirsName:John

LastName:Brown

Age:18

I click the Edit button, child window opens, change first name and then click accept, child window closes, the changes are in mysql database saved but the parent window still shows the old values. I do have a refresh method which works, but how can I call it from the child window or set it to be called after closing the child window?

Both Parent and Child Windows have controller and fxml. Any help would be appreciated.

Anarkie
  • 657
  • 3
  • 19
  • 46

4 Answers4

6

James_D's Answer (better)

Thanks to @James_D, you should use setOnHidden instead of setOnCloseRequest, that way you can again just call .close() and the EventHandler will be called.


My Answer

You could make use of setOnCloseRequest:

childStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
    public void handle(WindowEvent we) {
        // Refresh the parent window here
    }
});

To invoke this close request on a child form you can do:

    childStage.getOnCloseRequest().handle(new WindowEvent(childStage, WindowEvent.WINDOW_CLOSE_REQUEST));
    // or
    childStage.fireEvent(new WindowEvent(childStage, WindowEvent.WINDOW_CLOSE_REQUEST));

So you could implement the close button on the child stage like so:

Button closeButton = new Button("Close");
closeButton.setOnAction(event -> childStage.fireEvent(new WindowEvent(childStage, WindowEvent.WINDOW_CLOSE_REQUEST)));
erikvimz
  • 5,256
  • 6
  • 44
  • 60
  • Of course it didn't, you should replace my comment with your code to refresh the window contents. – erikvimz Jan 04 '16 at 13:13
  • Of course I added the refresh method, instead of your comment I added `refresh();` did not work, I added a simple `System.out.println("Closing Window ");` also did not work, `mytextArea.setText("test");` also did not work... – Anarkie Jan 04 '16 at 13:23
  • updates: if I close the child window from top right red x button; `setOnCloseRequest()` works but not with `stage.close();` – Anarkie Jan 04 '16 at 13:38
  • 3
    This is a bit of a hack. Use `childStage.setOnHidden(...)`, which is triggered whenever the window is hidden (no matter how), instead of `childStage.setOnCloseRequest(....)`, which is [only triggered by an OS-level request to close the window](http://docs.oracle.com/javase/8/javafx/api/javafx/stage/Window.html#onCloseRequestProperty) (e.g. by pressing the OS "close" button). Better still, use JavaFX Properties and bind your labels etc to them, as suggested in Antonio's answer. – James_D Jan 04 '16 at 14:05
  • I agree with you @James_D, I put your comment in my answer. – erikvimz Jan 04 '16 at 14:20
5

I think the best way to have automatic field updates in JavaFX is by the use of properties. If the name field in the parent window is bound to a SimpleStringProperty you only need to set the property's value when the child window is closed to notify the parent window of the update.

I made a small parent / child example to test the concept and the relevant piece of code is this, placed on the child creation method:

FXMLLoader loader = new FXMLLoader(getClass().getResource("Child.fxml"));
Parent root = loader.load();
ChildController controller = loader.getController();
name.textProperty().bind(controller.name.textProperty());

The field name is a Label in the parent and a TextField in the child. Any change in the child's text is immediately reflected in the parent.

This is an interesting topic. I will make a full example and post ir in my 'a cup of java' blog as soon as possible.

Antonio Raposo
  • 523
  • 6
  • 9
  • Of course, in real life you shouldn't expose UI controls from your controller like that. You can have your controllers share a model instance, and bind to/observe/modify properties in the model. See e.g. http://stackoverflow.com/questions/32342864/applying-mvc-with-javafx. A better way to manage things is to use a DI framework to inject the model into the controllers: [afterburner.fx](http://afterburner.adam-bien.com/) is designed for this. – James_D Jan 04 '16 at 16:53
  • Yes, I agree. Keep in mind that this is just a very simple example to see it working. In any real life application there should never be public fields exposing UI controls everywhere. – Antonio Raposo Jan 04 '16 at 17:00
4

If you use popup, you can set the method to showandwait instead of just show from the Stage object, and after run the method that update the GUI. Because showandwait method pause the main frame while the popup is running, once the popup closes it will run your update code.

stage.showAndWait();
updateGUI();
Christian Moen
  • 1,253
  • 2
  • 17
  • 31
  • Amazing. This code with `((Stage)(((Button)event.getSource()).getScene().getWindow())).close();` in my child controller class did the trick! – saytricky Feb 22 '23 at 10:57
0

we think we have two stage(window),1-parent stage,2-child window(pop up window)

  1. first send the stage object of parent stage to child stage

  2. in child stage set :

    childStage.setOnHidden(event->{ Parent root=FXMLLoader.load(getClass().getResource(parent fxml)); Scene scene=new Scene(root); parentStage.SetScene(scene); parentStage.show();

`