如何使用不同的fxml文件创建多个javafx控制器?

2022-09-01 13:08:21

我一直在看一些博客和其他堆栈溢出问题,我没有看到我的问题的直接答案。我正在创建一个javafx gui客户端,我想让我的菜单栏成为一个fxml中的一个控制器,然后我希望内容区域是额外的fxml文件。登录屏幕将是一个fxml,登录屏幕将是应用程序的主要内容,并且将在一个fxml中。我该怎么做?

我只是不想将我的登录,菜单栏和主要内容的所有代码都放在同一个文件中。这是我正在处理的图像:

enter image description here


答案 1

通过将自定义 Java 类用作 fx:root 和 FXML 文件的 fx:控制器,将 FXML 用作组件:http://docs.oracle.com/javafx/2/fxml_get_started/custom_control.htm

为此,您需要调用自定义java类FXMLLoader的构造函数,该构造函数将加载FXML。优点是可以更改 FXML 加载组件的方式。

使用嵌套控制器通过FXMLLoader实例化组件的经典方法是:首先是FXML,然后是每个部分的控制器。

使用这种技术,这是:首先是控制器,然后是每个组件的FXML。而且您不会直接在FXML中加载FXML,而是在FXML中导入自定义java类。

这是一个更好的抽象(当您在FXML中导入组件时,无需知道组件是如何实现的),并且有助于重用代码,因为它就像实现具有FXML支持的自定义小部件一样。要使组件可重用,请确保您的实现不会与其他部分紧密耦合,或者使用IOC来执行此操作(例如,与JavaFX的Spring集成)。这样,您就可以在应用程序的任何部分(就像DateInput小部件一样)导入组件,而不必担心,并且不会重复代码。

在您的情况下,您将拥有:

public class MenuBox extends VBox {

@FXML
private LoginBox loginBox;

@FXML
private ProfilesBox profilesBox;

public MenuBox() {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("menu.fxml"));
    fxmlLoader.setRoot(this);
    fxmlLoader.setController(this);
    try {
        fxmlLoader.load();
    } catch (IOException exception) {
        throw new RuntimeException(exception);
    }
}

public class LoginBox extends VBox {
public LoginBox() {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("login.fxml"));
    fxmlLoader.setRoot(this);
    fxmlLoader.setController(this);
    try {
        fxmlLoader.load();
    } catch (IOException exception) {
        throw new RuntimeException(exception);
    }
}

public class ProfilesBox extends VBox {
public ProfilesBox() {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("profiles.fxml"));
    fxmlLoader.setRoot(this);
    fxmlLoader.setController(this);
    try {
        fxmlLoader.load();
    } catch (IOException exception) {
        throw new RuntimeException(exception);
    }
}

您将在 menu.fxml 中导入 LoginBox 和 ProfilesBox,用于管理页面的全局布局:

<?import com.foo.bar.LoginBox ?>
<?import com.foo.bar.ProfilesBox ?>
<fx:root type="javafx.scene.layout.VBox"
    xmlns:fx="http://javafx.com/fxml">

<!-- Stuff here to declare the menu bar-->

    <HBox>
       <ProfilesBox fx:id="profilesBox"/>
       <LoginBox fx:id="loginBox"/>
    </HBox>

</fx:root>

login.fxml 和 profiles.fxml 只包含基本组件。


答案 2
  1. 您可以将 FXML 文档一个包含在另一个文档中 - 这应该可以帮助您分离设计逻辑

  2. 这意味着您可以拥有嵌套控制器 - 每个文档一个。

从文档中,您现在可以设置代码,以便可以分离逻辑以及从根控制器调用逻辑(如果需要)。

希望有所帮助。


推荐