Model view controller JavaFX在没有控制器的fxml中包含fxml

Model view controller JavaFX在没有控制器的fxml中包含fxml,model-view-controller,javafx,controller,fxml,Model View Controller,Javafx,Controller,Fxml,我正在用javafx编写一个应用程序。 这是一个带有主菜单的“多屏幕”应用程序,我可以从主菜单切换场景 我的场景在不同的fxml文件中定义 因为我尝试使用mvc模式,所以我没有在fxml文件中设置控制器,而是在FXMLloader上使用setController 一切都很好,但我有主菜单和它的所有功能,在单独的控制器和单独的fxml文件的操作 我已经试过了 <fx:include source="Menubar.fxml"/> startpage.fxml包括menubar.fxm

我正在用javafx编写一个应用程序。 这是一个带有主菜单的“多屏幕”应用程序,我可以从主菜单切换场景

我的场景在不同的fxml文件中定义

因为我尝试使用mvc模式,所以我没有在fxml文件中设置控制器,而是在FXMLloader上使用setController

一切都很好,但我有主菜单和它的所有功能,在单独的控制器和单独的fxml文件的操作

我已经试过了

<fx:include source="Menubar.fxml"/>

startpage.fxml
包括
menubar.fxml
,现在如何为menubar控件设置控制器?或者如何在每个其他控制器中轻松包含menubarController?

我认为您需要在加载器中使用
controllerFactory
来实现所需的功能。使用
controllerFactory
时,可以在FXML文件中指定控制器的类名,但控制器工厂允许您控制如何将其映射到对象(因此您仍然可以通过模型等来构造它)。当为
FXMLLoader
指定
controllerFactory
时,该工厂还用于为FXML文件中的任何
创建控制器

最后,请注意,可以将包含的fxml文件的控制器插入到“main”fxml文件中,如中所述

因此,如果startpage.fxml如下所示:

<!-- imports etc -->
<BorderPane fx:controller="com.example.Startpage" ... >
  <top>
    <fx:include source="Menubar.fxml" fx:id="menubar" />
  </top>
  <!-- etc ... -->
</BorderPane>

Menubar.fxml看起来像

<!-- imports etc -->
<MenuBar fx:controller="com.example.MenubarController" ... >
  <!-- etc... -->
</MenuBar>

然后,您可以通过以下方式控制控制器类的实例化:

FXMLLoader loader = new FXMLLoader(getClass().getResource("../fxml/startpage.fxml"));

Model m = ... ;

Startpage startpageController = new Startpage(m);
MenubarController menubarController = new MenubarController(m);

Callback<Class<?>, Object> controllerFactory = type -> {
    if (type == Startpage.class) {
        return startpageController ;
    } else if (type == MenubarController.class) {
        return menubarController ;
    } else { 
        // default behavior for controllerFactory:
        try {
            return type.newInstance();
        } catch (Exception exc) {
            exc.printStackTrace();
            throw new RuntimeException(exc); // fatal, just bail...
        }
    }
};

loader.setControllerFactory(controllerFactory);

Pane mainPane = loader.load();
fxmloader=newfxmloader(getClass().getResource(“../fxml/startpage.fxml”);
模型m=;
起始页起始页控制器=新起始页(m);
MenubarController MenubarController=新的MenubarController(m);

好吧,我需要更多的知识,我现在不明白你的答案。编辑我希望它能像“startpagecontroller扩展menucontroller”之类的简单。我想我仍然会在每个控制器中保留菜单栏的所有方法以及fxml代码..:/我真的帮不了你,除非我知道你不懂的地方。每个fxml文件都有一个与之关联的控制器实例。fxml文件可以为控制器指定一个类。因此,控制器工厂只是一个告诉
fxmloader
如何从指定类获取控制器实例的函数。复制方法或使一个控制器成为另一个控制器的子类都不会有帮助,因为您仍然有两个不同的控制器实例(因此它们不会引用相同的数据)。对我来说,最大的问题是理解您的解决方案(只是java初学者)和/或使您的示例适应我的代码。我会试着解释一下为什么我需要这些。首先,当我开始这个项目时,每个fxml文件都有自己的控制器,这很好,我可以在不丢失任何函数的情况下将每个fxml包含在彼此中。例如,我在应用程序“createproject”中有一个页面,该页面包含一些文本字段并包含菜单栏。当我使用menuitems将页面(场景)切换到“settingsforcreateproject”时,我再次将menubar包含在新的fxml中。看看这里,使用swing或awt时,一切都很好,也更愉快,但是我需要场景b中场景a中的数据,就像projectcreate场景中设置场景中的设置一样。我在我的主课上创建了一个模型,然后。。问题开始了,如何在控制器之间共享模型。我环顾四周,发现了一些听起来不错的解决方案,一个是设置控制器,但这个解决方案不适用于fxml,包括fxml。。现在我站在这里……好吧,我的解决方案确实做到了:在“主”控制器和包含的fxml的控制器之间共享一个模型。你不明白代码的哪些部分?
FXMLLoader loader = new FXMLLoader(getClass().getResource("../fxml/startpage.fxml"));

Model m = ... ;

Startpage startpageController = new Startpage(m);
MenubarController menubarController = new MenubarController(m);

Callback<Class<?>, Object> controllerFactory = type -> {
    if (type == Startpage.class) {
        return startpageController ;
    } else if (type == MenubarController.class) {
        return menubarController ;
    } else { 
        // default behavior for controllerFactory:
        try {
            return type.newInstance();
        } catch (Exception exc) {
            exc.printStackTrace();
            throw new RuntimeException(exc); // fatal, just bail...
        }
    }
};

loader.setControllerFactory(controllerFactory);

Pane mainPane = loader.load();
public class Startpage {

    public final Model m ;

    // note the name of this field must be xController,
    // where x is the fx:id set on the <fx:include>:

    @FXML
    private final MenubarController menubarController ;

    public Startpage(Model m) {
        this.m = m ;
    }

    // ...
}