3 Replies Latest reply: Mar 26, 2013 2:19 PM by 999067 RSS

    What's the best way to center the Dialog

    999067
      Hi,

      what is the best way to center a dialog in parent, if dialog was loaded from FXML?

      I tried this example:
      Re: What's the best way to create a Dialog

      but the method setOnShown() is wrong place for method recenter(), it's clearly visible how new dialog at the beginning appears in initial location and after that appears in the center.
      And if I try to use recenter() in method setOnShowing() - getWidth() and getHeight() are not available, and I cannot calculate correct central location.

      Can somebody help?

      Edited by: 996064 on 25.03.2013 15:32
        • 1. Re: What's the best way to center the Dialog
          999067
          ok I will ask another way.

          How to get width and height of the scene which was loaded from FXML before it's shown?
          • 2. Re: What's the best way to center the Dialog
            James_D
            996064 wrote:
            ok I will ask another way.

            How to get width and height of the scene which was loaded from FXML before it's shown?
            Short answer: you can't.

            Longer answer:

            I've found that calling show() on a stage will generally center it quite nicely on its owner (parent window). It appears slightly above the true center, which is quite nice visually.

            If you want more control, you could create bindings to the appropriate parts of the calculation (i.e. the x, y, width, and height of the owner, and the width and height of the dialog), and change the dialog's x and y when those values change. This should properly center the dialog immediately when it's shown. You probably want to turn the bindings off when the dialog is visible (else strange things will happen when you try to resize it), and turn the bindings back on again when it's hidden (so it reappears centered if you re-show it).

            Something like:
            import javafx.application.Application;
            import javafx.beans.property.DoubleProperty;
            import javafx.beans.property.SimpleDoubleProperty;
            import javafx.beans.value.ChangeListener;
            import javafx.beans.value.ObservableValue;
            import javafx.event.ActionEvent;
            import javafx.event.EventHandler;
            import javafx.scene.Scene;
            import javafx.scene.control.Button;
            import javafx.scene.layout.BorderPane;
            import javafx.scene.text.Text;
            import javafx.stage.Modality;
            import javafx.stage.Stage;
            import javafx.stage.Window;
            import javafx.stage.WindowEvent;
            
            public class CenteredDialog extends Application {
            
              @Override
              public void start(Stage primaryStage) {
                final BorderPane root = new BorderPane();
                final Button button = new Button("Show Dialog");
                root.setBottom(button);
                root.setCenter(new Text("Main Window"));
                final Stage dialog = createDialog(primaryStage);
                button.setOnAction(new EventHandler<ActionEvent>() {
                  @Override
                  public void handle(ActionEvent event) {
                    dialog.show();
                  }
                });
                Scene scene = new Scene(root, 300, 200);
                primaryStage.setScene(scene);
                primaryStage.show();
              }
            
              private Stage createDialog(final Window parentWindow) {
                final Stage dialog = new Stage();
                dialog.initOwner(parentWindow);
                dialog.initModality(Modality.WINDOW_MODAL);
                final BorderPane root = new BorderPane();
                root.setCenter(new Text("Dialog"));
                final Button button = new Button("Dismiss");
                button.setOnAction(new EventHandler<ActionEvent>() {
                  @Override
                  public void handle(ActionEvent event) {
                    dialog.hide();
                  }
                });
                root.setBottom(button);
            
                Scene scene = new Scene(root, 200, 100);
                dialog.setScene(scene);
            
                // Desired x coordinate for centered dialog
                final DoubleProperty x = new SimpleDoubleProperty();
                x.bind(parentWindow.xProperty()
                    .add(
                        parentWindow.widthProperty().subtract(dialog.widthProperty()).divide(2)
                     )
                );
            
                // Desired x coordinate for centered dialog
                final DoubleProperty y = new SimpleDoubleProperty();
                y.bind(parentWindow.yProperty()
                    .add(
                        parentWindow.heightProperty().subtract(dialog.heightProperty()).divide(2)
                    )
                );
            
                // Update dialog's x coordinate when x defined above changes
                x.addListener(new ChangeListener<Number>() {
                  @Override
                  public void changed(ObservableValue<? extends Number> obs, Number oldValue, Number newValue) {
                    dialog.setX(newValue.doubleValue());
                  }
                });
            
                // Update dialog's y coordinate when y defined above changes
                y.addListener(new ChangeListener<Number>() {
                  @Override
                  public void changed(ObservableValue<? extends Number> obs, Number oldValue, Number newValue) {
                    dialog.setY(newValue.doubleValue());
                  }
                });
            
                // Unbind x and y when dialog has been shown, to allow user to resize without interference
                dialog.setOnShown(new EventHandler<WindowEvent>() {
                  @Override
                  public void handle(WindowEvent event) {
                    x.unbind();
                    y.unbind();
                  }
                });
            
                // Rebind x and y when dialog is hidden, so re-showing will properly center it again
                dialog.setOnHidden(new EventHandler<WindowEvent>() {
                  @Override
                  public void handle(WindowEvent event) {
                    x.unbind();
                    x.bind(parentWindow.xProperty()
                        .add(
                            parentWindow.widthProperty().subtract(dialog.widthProperty()).divide(2)
                        )
                    );
                    y.unbind();
                    y.bind(parentWindow.yProperty()
                        .add(
                            parentWindow.heightProperty().subtract(dialog.heightProperty()).divide(2)
                        )
                    );
                  }
                });
            
                return dialog;
              }
            
              public static void main(String[] args) {
                launch(args);
              }
            }
            • 3. Re: What's the best way to center the Dialog
              999067
              Thanks for the code, it works like expected.