Gus
Gus

Reputation: 413

FXML BorderPane centered inside another BorderPane

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):


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:

**Current layout:**

Result that I'm looking for (roughly)

**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;

Idea

Red border: Stage -> Scene -> BorderPane Blue border: BorderPane loaded through FXML in the method showNewScene(FXMLPath)

layout explanation

(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

Answers (2)

Gus
Gus

Reputation: 413

As James_D said in the comments:

Add an alignment="CENTER" attribute to the GridPane root element in the FXML.

Upvotes: 0

Luvy
Luvy

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

Related Questions