Reputation: 413
So, I've been trying to center a BorderPane inside another BorderPane (center part), but so far without success.
I've tried (both in the Pane loaded from FXML and parent Scene):
SetPadding
setMargin
AnchorPane
and setting Top, bottom, left and right anchorsRegions
to the top and left of the main BorderPane (ineffective and does not work when resizing the Stage)If I use anything other than a Pane or Node to load the FXML
Pane pane = loader.load();
Like an HBox, VBox, AnchorPane, or Group the FXML does not load;
Current layout:
Result that I'm looking for (roughly)
The idea is even when I resize the window, the FXML layout will stay in the center of the MainBorderPane;
Red border: Stage -> Scene -> BorderPane
Blue border: BorderPane loaded through FXML in the method showNewScene(FXMLPath)
(source code for simulation: package sample)
Main.java
package sample;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class Main extends Application {
private static BorderPane mainBorderPane;
private static Scene mainScene;
private static MenuBar mainMenuBar;
private static Stage mainStage;
private static Menu mainMenuFile;
private static MenuItem mainItemMenuLock;
private static MenuItem mainItemMenuClose;
private static Menu mainMenuHelp;
private static MenuItem mainItemMenuSupport;
public static BorderPane getMainBorderPane() {
if (mainBorderPane == null) {
mainBorderPane = new BorderPane();
}
return mainBorderPane;
}
public static Scene getMainScene() {
if (mainScene == null) {
mainScene = new Scene(getMainBorderPane(), 800, 600);
}
return mainScene;
}
public static MenuBar getMainMenuBar() {
if (mainMenuBar == null) {
mainMenuBar = new MenuBar();
mainMenuFile = new Menu("File");
mainItemMenuLock = new MenuItem("Lock Screen");
mainItemMenuClose = new MenuItem("Close");
mainMenuFile.getItems().addAll(mainItemMenuLock, mainItemMenuClose);
mainMenuHelp = new Menu("Help");
mainItemMenuSupport = new MenuItem("Support");
mainMenuHelp.getItems().addAll(mainItemMenuSupport);
mainMenuBar.getMenus().addAll(mainMenuFile, mainMenuHelp);
}
return mainMenuBar;
}
public static Stage getMainStage() {
if (mainStage == null) {
getMainBorderPane().setTop(getMainMenuBar());
mainStage = new Stage(StageStyle.DECORATED);
}
return mainStage;
}
public static void main(String[] args) {
launch(args);
}
@Override
public void init() {
//
}
@Override
public void start(final Stage initStage) throws Exception{
UtilMethods.showNewScene("login.fxml");
}
}
UtilMethods.java
package sample;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Pos;
import javafx.scene.layout.Pane;
public class UtilMethods {
public static void showNewScene(String fxmlPath) {
try {
FXMLLoader loader = new FXMLLoader(UtilMethods.class.getResource(fxmlPath));
Pane pane = loader.load();
Main.getMainBorderPane().setCenter(pane);
Main.getMainBorderPane().setAlignment(pane, Pos.CENTER);
Main.getMainStage().setScene(Main.getMainScene());
Main.getMainStage().setAlwaysOnTop(false);
Main.getMainStage().setResizable(true);
Main.getMainStage().show();
}catch (java.io.IOException e){
System.out.println("Error loading screen" + e.getMessage());
}
}
}
LoginController.java
package sample;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
public class LoginController {
@FXML private TextField userIdField;
@FXML private PasswordField passwordField;
public void initialize(){
//
}
@FXML
private void login(ActionEvent event) {
System.out.println("login");
}
@FXML
private void cancel(){
userIdField.clear();
passwordField.clear();
userIdField.requestFocus();
}
@FXML
private void registerNew(ActionEvent event) throws Exception{
System.out.println("register new");
}
}
login.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<GridPane xmlns:fx="http://javafx.com/fxml/1" hgap="10" vgap="10"
fx:controller="sample.LoginController" GridPane.halignment="CENTER" GridPane.valignment="CENTER">
<padding>
<Insets top="10" right="10" bottom="10" left="10"/>
</padding>
<children>
<Label text="Username:" GridPane.columnIndex="0"
GridPane.rowIndex="0" GridPane.halignment="RIGHT" />
<Label text="Password:" GridPane.columnIndex="0"
GridPane.rowIndex="1" GridPane.halignment="RIGHT" />
<Label text="Database connection status:" GridPane.columnIndex="0"
GridPane.rowIndex="2" GridPane.halignment="RIGHT" />
<Label fx:id="labelDBStatus" text="..." GridPane.columnIndex="1"
GridPane.rowIndex="2" GridPane.halignment="RIGHT" />
<TextField fx:id="userIdField" GridPane.columnIndex="1" GridPane.rowIndex="0"
promptText="User ID" styleClass="text-field"/>
<PasswordField fx:id="passwordField" GridPane.columnIndex="1" GridPane.rowIndex="1"
promptText="Password" styleClass="text-field"/>
<HBox GridPane.columnIndex="0" GridPane.rowIndex="3"
GridPane.columnSpan="2" alignment="CENTER" spacing="10">
<children>
<Button fx:id="btnLogin" text="Login" onAction="#login" />
<Button fx:id="btnCancel" text="Cancel" onAction="#cancel"/>
<Button fx:id="btnRegister" text="Register" onAction="#registerNew"/>
</children>
</HBox>
</children>
</GridPane>
Upvotes: 0
Views: 3369
Reputation: 413
As James_D said in the comments:
Add an alignment="CENTER" attribute to the GridPane root element in the FXML.
Upvotes: 0
Reputation: 96
The reason you get this, is due to the fact that if a certain area does not contain subcomponents, that area may be occupied by other areas. In this case since your GridPane is the only component in the BorderPane, it automatically goes to the upper left. To avoid this, you must either have other components in the border pane OR consider using something like a VBox (instead of a gridPane) which inherits its parents dimensions so that your screen will be centred.
Upvotes: 0