JavaFX,从另一个文件中将锚定窗格元素与FXML交换

时间:2018-11-03 00:29:23

标签: java javafx

我想在JavaFX中创建一个动态UI,类似于下图,左侧菜单将包含在其自己的锚定窗格中,而当前选择的项目将确定右侧锚定窗格中填充的内容。

使用这种布局,我希望能够用一个单独的文件中声明的定位窗格替换掉整个右侧的定位窗格,以尝试使其保持模块化。这是首选方法,而不是在同一文件中全部声明并在不使用时将其隐藏起来?如果这是正确的方法,您该怎么做呢?

enter image description here

这个问题有点笼统,但是我找不到任何可以显示上述操作方法的参考文献,所以请多多包涵。

1 个答案:

答案 0 :(得分:1)

您可以加载新的FXML文档并将其设置为右侧AnchorPane的子级。

下面是一个非常粗糙的示例应用程序,显示了实际的概念。基本上,这项工作是通过loadPage()方法完成的,您将要适应您的用法,因为此示例仅用于说明概念。

Main.java

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class Main extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {

        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("MainLayout.fxml"));
            loader.setController(new MainController());

            primaryStage.setScene(new Scene(loader.load()));

            primaryStage.show();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

MainLayout.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.*?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0"
            prefWidth="600.0" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1">
    <center>
        <AnchorPane fx:id="paneMainContent" prefHeight="200.0" prefWidth="200.0"
                    style="-fx-border-color: black; -fx-border-width: 2px;" BorderPane.alignment="CENTER"/>
    </center>
    <left>
        <GridPane BorderPane.alignment="CENTER">
            <columnConstraints>
                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
            </columnConstraints>
            <rowConstraints>
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
            </rowConstraints>
            <VBox fx:id="vboxShowCats" alignment="CENTER" prefHeight="200.0" prefWidth="100.0"
                  style="-fx-border-color: black; -fx-border-width: 2px;">
                <Button fx:id="btnShowCats" mnemonicParsing="false" text="Show Cats"/>
            </VBox>
            <VBox fx:id="vboxShowDogs" alignment="CENTER" prefHeight="200.0" prefWidth="100.0"
                  style="-fx-border-color: black; -fx-border-width: 2px;" GridPane.rowIndex="1">
                <Button fx:id="btnShowDogs" mnemonicParsing="false" text="Show Dogs"/>
            </VBox>
            <VBox fx:id="vboxShowBirds" alignment="CENTER" prefHeight="200.0" prefWidth="100.0"
                  style="-fx-border-color: black; -fx-border-width: 2px;" GridPane.rowIndex="2">
                <Button fx:id="btnShowBirds" mnemonicParsing="false" text="Show Birds"/>
            </VBox>
        </GridPane>
    </left>
</BorderPane>

MainController.java

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import java.io.IOException;

public class MainController {

    @FXML
    private AnchorPane paneMainContent;
    @FXML
    private VBox vboxShowCats;
    @FXML
    private Button btnShowCats;
    @FXML
    private VBox vboxShowDogs;
    @FXML
    private Button btnShowDogs;
    @FXML
    private VBox vboxShowBirds;
    @FXML
    private Button btnShowBirds;

    @FXML
    private void initialize() {

        btnShowCats.setOnAction(event -> loadPage("Cats"));
        btnShowDogs.setOnAction(event -> loadPage("Dogs"));
        btnShowBirds.setOnAction(event -> loadPage("Birds"));

    }

    private void loadPage(String name) {

        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource(name + "View.fxml"));

            AnchorPane newPane = loader.load();

            // Set the loaded FXML file as the content of our main right-side pane
            paneMainContent.getChildren().setAll(newPane);

            // Reset the anchors
            AnchorPane.setBottomAnchor(newPane, 0.0);
            AnchorPane.setLeftAnchor(newPane, 0.0);
            AnchorPane.setRightAnchor(newPane, 0.0);
            AnchorPane.setTopAnchor(newPane, 0.0);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

CatsView.fxml,DogsView.fxml,BirdsView.fxml Label以外的所有内容均相同:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.*?>
<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/9.0.1"
            xmlns:fx="http://javafx.com/fxml/1">
    <VBox alignment="CENTER" prefHeight="400.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0"
          AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
        <Label style="-fx-font-size: 200%;" text="These are CATS!"/>
    </VBox>
</AnchorPane>

  

结果:

screenshot

我敢肯定,有更多更高级(更可取的)方法可以做到这一点,但是它确实有效,这也是我做到的方式(尽管我仍在学习自己)。

此外,我显然没有理会这个示例的样式:)