【问题标题】:FXML BorderPane centered inside another BorderPaneFXML BorderPane 在另一个 BorderPane 内居中
【发布时间】:2018-04-17 03:54:51
【问题描述】:

所以,我一直在尝试将 BorderPane 居中在另一个 BorderPane(中心部分)内,但到目前为止没有成功。

我已经尝试过(在从 FXML 和父场景加载的窗格中):

  • SetPadding
  • setMargin
  • 使用AnchorPane 并设置顶部、底部、左侧和右侧锚点
  • 在主 BorderPane 的顶部和左侧添加 Regions(无效且在调整舞台大小时不起作用)

如果我使用 PaneNode 以外的任何东西来加载 FXML

Pane pane = loader.load();

像 HBox、VBox、AnchorPane 或 Group 一样,FXML 不会加载;


当前布局:

我正在寻找的结果(大致)

这个想法是即使我调整窗口大小时,FXML 布局也会留在 MainBorderPane 的中心;

红色边框:舞台 -> 场景 -> BorderPane 蓝色边框:在方法showNewScene(FXMLPath)中通过FXML加载的BorderPane@

(仿真源代码:包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>

【问题讨论】:

  • 你为什么不使用StackPane
  • 我从 FXMLLoader 得到一个异常:线程“JavaFX 应用程序线程”中的异常 java.lang.ClassCastException:javafx.scene.layout.GridPane 无法转换为 javafx.scene.layout.StackPane - 我的理解是我的布局 login.fxml 是一个 GridPane,GridPane 和 StackPane 都继承自 javafx.scene.layout.Pane,
  • “使用StackPane”我认为@BoHalim 的意思是使用StackPane 而不是BorderPane。是否将alignment="CENTER" 属性添加到 FXML 中的 GridPane 根元素使其执行您想要的操作?
  • alignment="CENTER" 确实如此。谢谢!之前没有尝试将属性放入 FXML。欣赏它,

标签: java javafx


【解决方案1】:

之所以会这样,是因为如果某个区域不包含子组件,则该区域可能被其他区域占用。在这种情况下,由于您的 GridPane 是 BorderPane 中的唯一组件,它会自动转到左上角。为避免这种情况,您必须在边框窗格中有其他组件,或者考虑使用继承其父尺寸的 VBox(而不是 gridPane)之类的东西,以便您的屏幕居中。

【讨论】:

    【解决方案2】:

    正如 James_D 在 cmets 中所说:

    在 GridPane 根元素中添加 alignment="CENTER" 属性 FXML。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多