title: JavaFX position dialog and stage in center of screen
body: <p>The following codes demonstrates centering of a dialog and the stage in the center of the screen. The dialog is supposed to be displayed first for the user to enter the login credentials. After successful login, the main window (stage) is then displayed. I found the solution of centering the dialog and stage from this web site, but it doesn't seem very ideal. For both the dialog and stage, they have to be displayed first before we can calculate the coordinates and then positioning them in the center. This means that we can see the dialog and the main window moving to the center after they are displayed. Is there a better way? Ideally, they should be positioned in the center before they are displayed.</p>
  
  <pre><code>import javafx.application.Application;
  import javafx.application.Platform;
  import javafx.beans.property.SimpleStringProperty;
  import javafx.beans.property.StringProperty;
  import javafx.concurrent.Task;
  import javafx.event.ActionEvent;
  import javafx.geometry.Insets;
  import javafx.geometry.Pos;
  import javafx.geometry.Rectangle2D;
  import javafx.scene.Cursor;
  import javafx.scene.Scene;
  import javafx.scene.control.Alert;
  import javafx.scene.control.Button;
  import javafx.scene.control.ButtonType;
  import javafx.scene.control.Dialog;
  import javafx.scene.control.Label;
  import javafx.scene.control.PasswordField;
  import javafx.scene.control.TableColumn;
  import javafx.scene.control.TableView;
  import javafx.scene.control.TextField;
  import javafx.scene.control.Alert.AlertType;
  import javafx.scene.layout.GridPane;
  import javafx.scene.layout.VBox;
  import javafx.scene.text.Text;
  import javafx.stage.Screen;
  import javafx.stage.Stage;
  import javafx.stage.Window;
  
  public class Demo extends Application {
  
      private Stage primaryStage;
      private Dialog&lt;String&gt; dialog;
      private Button createUserButton = new Button("Create User");
  
      @Override
      public void start(Stage primaryStage) throws Exception {
          this.primaryStage = primaryStage;
          Text usersLabel = new Text("Current Users:");
          TableColumn&lt;User, String&gt; indexColumn = new TableColumn&lt;User, String&gt;("No.");
          indexColumn.setMaxWidth(1f * Integer.MAX_VALUE * 10);
          indexColumn.setCellValueFactory(p -&gt; p.getValue().indexProperty());
          TableColumn&lt;User, String&gt; userNameColumn = new TableColumn&lt;User, String&gt;("User Name");
          userNameColumn.setMaxWidth(1f * Integer.MAX_VALUE * 60);
          userNameColumn.setCellValueFactory(p -&gt; p.getValue().userNameProperty());
          TableColumn&lt;User, String&gt; roleColumn = new TableColumn&lt;User, String&gt;("Role");
          roleColumn.setMaxWidth(1f * Integer.MAX_VALUE * 30);
          roleColumn.setCellValueFactory(p -&gt; p.getValue().roleProperty());
          TableView&lt;User&gt; tableView = new TableView&lt;User&gt;();
          tableView.getColumns().add(indexColumn);
          tableView.getColumns().add(userNameColumn);
          tableView.getColumns().add(roleColumn);
          tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
          Text dummyLabel = new Text("");
          VBox leftPane = new VBox(5);
          leftPane.getChildren().addAll(usersLabel, tableView);
          VBox rightPane = new VBox(20);
          rightPane.setFillWidth(true);
          rightPane.getChildren().addAll(dummyLabel, createUserButton);
          GridPane mainPane = new GridPane();
          mainPane.setPadding(new Insets(10, 0, 0, 10));
          mainPane.setHgap(20);
          mainPane.add(leftPane, 0, 0);
          mainPane.add(rightPane, 1, 0);
          Scene scene = new Scene(mainPane);
          primaryStage.setScene(scene);
          primaryStage.setResizable(false);
          showDialog();
      }
  
      private void showDialog() {
          dialog = new Dialog&lt;&gt;();
          dialog.setTitle("Login");
          dialog.setHeaderText("Please enter User Name and Password to login.");
          dialog.setResizable(false);
          Label userNameLabel = new Label("User Name:");
          Label passwordLabel = new Label("Password:");
          TextField userNameField = new TextField();
          PasswordField passwordField = new PasswordField();
          GridPane grid = new GridPane();
          grid.setAlignment(Pos.CENTER);
          grid.setHgap(10);
          grid.setVgap(10);
          grid.setPadding(new Insets(20, 35, 20, 35));
          grid.add(userNameLabel, 1, 1);
          grid.add(userNameField, 2, 1);
          grid.add(passwordLabel, 1, 2);
          grid.add(passwordField, 2, 2);
          dialog.getDialogPane().setContent(grid);
          dialog.getDialogPane().getButtonTypes().add(ButtonType.OK);
          Button okButton = (Button) dialog.getDialogPane().lookupButton(ButtonType.OK);
          okButton.addEventFilter(ActionEvent.ACTION, event -&gt; {
              createUser(userNameField.getText().trim(), passwordField.getText());
              event.consume();
          });
          dialog.getDialogPane().getButtonTypes().add(ButtonType.CANCEL);
          Platform.runLater(() -&gt; {
              Rectangle2D screenBounds = Screen.getPrimary().getVisualBounds();
              Window window = dialog.getDialogPane().getScene().getWindow();
              window.setX((screenBounds.getWidth() - window.getWidth()) / 2);
              window.setY((screenBounds.getHeight() - window.getHeight()) / 2);
          });
          dialog.showAndWait();
      }
  
      private void createUser(String userName, String password) {
          dialog.getDialogPane().setDisable(true);
          dialog.getDialogPane().getScene().setCursor(Cursor.WAIT);
          Task&lt;Boolean&gt; task = new Task&lt;Boolean&gt;() {
              @Override
              public Boolean call() {
                  try {
                      Thread.sleep(100);
                  } catch (InterruptedException exception) {
                  }
                  return Boolean.TRUE;
              }
          };
          task.setOnSucceeded(e -&gt; {
              Boolean success = task.getValue();
              dialog.getDialogPane().setDisable(false);
              dialog.getDialogPane().getScene().setCursor(Cursor.DEFAULT);
              if (success.booleanValue()) {
                  Platform.runLater(() -&gt; {
                      dialog.close();
                      primaryStage.show();
                      Rectangle2D screenBounds = Screen.getPrimary().getVisualBounds();
                      primaryStage.setX((screenBounds.getWidth() - primaryStage.getWidth()) / 2);
                      primaryStage.setY((screenBounds.getHeight() - primaryStage.getHeight()) / 2);
                  });
              } else {
                  Alert alert = new Alert(AlertType.ERROR);
                  alert.setTitle("Login Error");
                  alert.setHeaderText("Unable to login.");
                  alert.showAndWait();
              }
          });
          new Thread(task).start();
      }
  
      public static void main(String[] arguments) {
          Application.launch(arguments);
      }
  
  }
  
  class User {
  
      private StringProperty index;
  
      private StringProperty userName;
  
      private StringProperty role;
  
      public String getIndex() {
          return indexProperty().get();
      }
  
      public StringProperty indexProperty() {
          if (index == null) {
              index = new SimpleStringProperty(this, "index");
          }
          return index;
      }
  
      public void setIndex(String index) {
          indexProperty().set(index);
      }
  
      public String getUserName() {
          return userNameProperty().get();
      }
  
      public StringProperty userNameProperty() {
          if (userName == null) {
              userName = new SimpleStringProperty(this, "userName");
          }
          return userName;
      }
  
      public void setUserName(String userName) {
          userNameProperty().set(userName);
      }
  
      public String getRole() {
          return roleProperty().get();
      }
  
      public StringProperty roleProperty() {
          if (role == null) {
              role = new SimpleStringProperty(this, "role");
          }
          return role;
      }
  
      public void setRole(String role) {
          roleProperty().set(role);
      }
  
  }
  </code></pre>
  
  <p>Below is solution by setting custom dimensions to stage and dialog. It works for the stage but it doesn't work for the dialog.</p>
  
  <pre><code>import javafx.application.Application;
  import javafx.application.Platform;
  import javafx.beans.property.SimpleStringProperty;
  import javafx.beans.property.StringProperty;
  import javafx.concurrent.Task;
  import javafx.event.ActionEvent;
  import javafx.geometry.Insets;
  import javafx.geometry.Pos;
  import javafx.geometry.Rectangle2D;
  import javafx.scene.Cursor;
  import javafx.scene.Scene;
  import javafx.scene.control.Alert;
  import javafx.scene.control.Button;
  import javafx.scene.control.ButtonType;
  import javafx.scene.control.Dialog;
  import javafx.scene.control.Label;
  import javafx.scene.control.PasswordField;
  import javafx.scene.control.TableColumn;
  import javafx.scene.control.TableView;
  import javafx.scene.control.TextField;
  import javafx.scene.control.Alert.AlertType;
  import javafx.scene.layout.GridPane;
  import javafx.scene.layout.VBox;
  import javafx.scene.text.Text;
  import javafx.stage.Screen;
  import javafx.stage.Stage;
  import javafx.stage.Window;
  import javafx.stage.WindowEvent;
  
  public class Demo extends Application {
  
      private Stage primaryStage;
      private Dialog&lt;String&gt; dialog;
      private Button createUserButton = new Button("Create User");
  
      @Override
      public void start(Stage primaryStage) throws Exception {
          this.primaryStage = primaryStage;
          Text usersLabel = new Text("Current Users:");
          TableColumn&lt;User, String&gt; indexColumn = new TableColumn&lt;User, String&gt;("No.");
          indexColumn.setMaxWidth(1f * Integer.MAX_VALUE * 10);
          indexColumn.setCellValueFactory(p -&gt; p.getValue().indexProperty());
          TableColumn&lt;User, String&gt; userNameColumn = new TableColumn&lt;User, String&gt;("User Name");
          userNameColumn.setMaxWidth(1f * Integer.MAX_VALUE * 60);
          userNameColumn.setCellValueFactory(p -&gt; p.getValue().userNameProperty());
          TableColumn&lt;User, String&gt; roleColumn = new TableColumn&lt;User, String&gt;("Role");
          roleColumn.setMaxWidth(1f * Integer.MAX_VALUE * 30);
          roleColumn.setCellValueFactory(p -&gt; p.getValue().roleProperty());
          TableView&lt;User&gt; tableView = new TableView&lt;User&gt;();
          tableView.getColumns().add(indexColumn);
          tableView.getColumns().add(userNameColumn);
          tableView.getColumns().add(roleColumn);
          tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
          Text dummyLabel = new Text("");
          VBox leftPane = new VBox(5);
          leftPane.getChildren().addAll(usersLabel, tableView);
          VBox rightPane = new VBox(20);
          rightPane.setFillWidth(true);
          rightPane.getChildren().addAll(dummyLabel, createUserButton);
          GridPane mainPane = new GridPane();
          mainPane.setPadding(new Insets(10, 0, 0, 10));
          mainPane.setHgap(20);
          mainPane.add(leftPane, 0, 0);
          mainPane.add(rightPane, 1, 0);
          float width = 372f;
          float height = 470f;
          Scene scene = new Scene(mainPane, width, height);
          primaryStage.setScene(scene);
          primaryStage.setResizable(false);
          Rectangle2D screenBounds = Screen.getPrimary().getVisualBounds();
          primaryStage.setX((screenBounds.getWidth() - width) / 2);
          primaryStage.setY((screenBounds.getHeight() - height) / 2);
          showDialog();
      }
  
      private void showDialog() {
          dialog = new Dialog&lt;&gt;();
          dialog.setTitle("Login");
          dialog.setHeaderText("Please enter User Name and Password to login.");
          dialog.setResizable(false);
          Label userNameLabel = new Label("User Name:");
          Label passwordLabel = new Label("Password:");
          TextField userNameField = new TextField();
          PasswordField passwordField = new PasswordField();
          GridPane grid = new GridPane();
          grid.setAlignment(Pos.CENTER);
          grid.setHgap(10);
          grid.setVgap(10);
          grid.setPadding(new Insets(20, 35, 20, 35));
          grid.add(userNameLabel, 1, 1);
          grid.add(userNameField, 2, 1);
          grid.add(passwordLabel, 1, 2);
          grid.add(passwordField, 2, 2);
          dialog.getDialogPane().setContent(grid);
          dialog.getDialogPane().getButtonTypes().add(ButtonType.OK);
          Button okButton = (Button) dialog.getDialogPane().lookupButton(ButtonType.OK);
          okButton.addEventFilter(ActionEvent.ACTION, event -&gt; {
              login(userNameField.getText().trim(), passwordField.getText());
              event.consume();
          });
          dialog.getDialogPane().getButtonTypes().add(ButtonType.CANCEL);
          float width = 509f;
          float height = 168f;
          dialog.setWidth(width);
          dialog.setHeight(height);
          Rectangle2D screenBounds = Screen.getPrimary().getVisualBounds();
          dialog.setX((screenBounds.getWidth() - width) / 2);
          dialog.setY((screenBounds.getHeight() - height) / 2);
          dialog.showAndWait();
      }
  
      private void login(String userName, String password) {
          dialog.getDialogPane().setDisable(true);
          dialog.getDialogPane().getScene().setCursor(Cursor.WAIT);
          Task&lt;Boolean&gt; task = new Task&lt;Boolean&gt;() {
              @Override
              public Boolean call() {
                  try {
                      Thread.sleep(100);
                  } catch (InterruptedException exception) {
                  }
                  return Boolean.TRUE;
              }
          };
          task.setOnSucceeded(e -&gt; {
              Boolean success = task.getValue();
              dialog.getDialogPane().setDisable(false);
              dialog.getDialogPane().getScene().setCursor(Cursor.DEFAULT);
              if (success.booleanValue()) {
                  Platform.runLater(() -&gt; {
                      primaryStage.show();
                  });
              } else {
                  Alert alert = new Alert(AlertType.ERROR);
                  alert.setTitle("Login Error");
                  alert.setHeaderText("Unable to login.");
                  alert.showAndWait();
              }
          });
          new Thread(task).start();
      }
  
      public static void main(String[] arguments) {
          Application.launch(arguments);
      }
  
  }
  
  class User {
  
      private StringProperty index;
  
      private StringProperty userName;
  
      private StringProperty role;
  
      public String getIndex() {
          return indexProperty().get();
      }
  
      public StringProperty indexProperty() {
          if (index == null) {
              index = new SimpleStringProperty(this, "index");
          }
          return index;
      }
  
      public void setIndex(String index) {
          indexProperty().set(index);
      }
  
      public String getUserName() {
          return userNameProperty().get();
      }
  
      public StringProperty userNameProperty() {
          if (userName == null) {
              userName = new SimpleStringProperty(this, "userName");
          }
          return userName;
      }
  
      public void setUserName(String userName) {
          userNameProperty().set(userName);
      }
  
      public String getRole() {
          return roleProperty().get();
      }
  
      public StringProperty roleProperty() {
          if (role == null) {
              role = new SimpleStringProperty(this, "role");
          }
          return role;
      }
  
      public void setRole(String role) {
          roleProperty().set(role);
      }
  
  }
  </code></pre>
  
  <p>JKostikiadis's solution:</p>
  
  <pre><code>import javafx.application.Application;
  import javafx.geometry.Pos;
  import javafx.geometry.Rectangle2D;
  import javafx.scene.Scene;
  import javafx.scene.control.Alert;
  import javafx.scene.control.Alert.AlertType;
  import javafx.scene.control.Button;
  import javafx.scene.layout.HBox;
  import javafx.stage.Screen;
  import javafx.stage.Stage;
  
  public class TestApp extends Application {
  
      private static final double WIDTH = 316.0;
      private static final double HEIGHT = 339.0;
  
      public static void main(String[] args) {
          launch(args);
      }
  
      @Override
      public void start(Stage stage) throws Exception {
  
          HBox pane = new HBox();
          pane.setAlignment(Pos.CENTER);
  
          Button b = new Button("click me");
          b.setOnAction(e -&gt; {
              showDialog();
          });
  
          pane.getChildren().add(b);
  
          Scene scene = new Scene(pane, 300, 300);
  
          stage.setScene(scene);
  
          centerStage(stage, WIDTH, HEIGHT);
          stage.show();
  
  
      }
  
      private void showDialog() {
          Alert dialog = new Alert(AlertType.ERROR);
          dialog.setTitle("Error Dialog");
          dialog.setHeaderText("Look, an Error Dialog");
          dialog.setContentText("Ooops, there was an error!\nOoops, there was an error!");
  
          Stage stage = (Stage) dialog.getDialogPane().getScene().getWindow();
          centerStage(stage, -10000, -10000);
          dialog.show();
          System.out.println(stage.getWidth() + " " + stage.getHeight());
          dialog.hide();
          centerStage(stage, stage.getWidth(), stage.getHeight());        
          dialog.showAndWait();
  
      }
  
      private void centerStage(Stage stage, double width, double height) {
          Rectangle2D screenBounds = Screen.getPrimary().getVisualBounds();
          stage.setX((screenBounds.getWidth() - width) / 2);
          stage.setY((screenBounds.getHeight() - height) / 2);
      }
  }
  </code></pre>