当前位置: 首页 > 知识库问答 >
问题:

具有多个不同控制器的JavaFX1 FXML文件?

岳朝
2023-03-14

在我的应用程序中有两个不同的阶段,它们是使用相同FXML文件的帮助屏幕。而不是创建两个FXML文件,我想只使用一个,并有两个控制器调用相同的fxml。

唯一的问题是控制器是在FXML文件中分配的。那么,有没有一种方法可以通过控制器类本身中的代码来更改指定的控制器?

我真的希望避免复制一个FXML文件,只是为了更改每个文件中的控制器。提前谢谢。

共有2个答案

萧麒
2023-03-14

在FXML文件中,

setControlllerFactor函数需要一个Callback类型,这是一个只有一个可调用函数的接口:工厂使用的call。该函数(由FXMLLoader类调用)期望获得一个Class对象作为输入参数,并根据类型提供实例化对象。以上Java8 lambdas可用于为工厂提供:

FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(fxmlFile));
loader.setControllerFactory((Class<?> controllerType) ->{
    if(controllerType == Controller.class){
        return new Controller();
    }
});
Parent root = (Parent) fxmlLoader.load();

上述代码中的参数controllerType是由fxmlfx:controller属性提供的类型,该属性由Java类加载器确定。调用Controllerfactory时,还没有实例化任何内容,这就是为什么fxml中甚至可以给出抽象类。为了实现不同的行为,可以使用继承。

例如:

class Controller{...}
class FirstController extends Controller{...}
class SecondController extends Controller{...}

工厂可以这样使用:

FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(fxmlFile));
final int[] instantiatedClasses  = {0};
loader.setControllerFactory((Class<?> controllerType) ->{
    if(controllerType == Controller.class){
        if(0 == instantiatedClasses[0]){
            ++instantiatedClasses[0];
            return new FirstController();
        } else return new SecondController();
    }
});
Parent root = (Parent) fxmlLoader.load();

请注意,通过这种方式,也可以向控制器提供不同的参数,因此继承可能是一种过激行为。例如,可以向控制器提供初级阶段,例如,用于消除控制器中不同设置器的需要。

class Controller{
    public Controller(int behaviorParam){...}
}
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(fxmlFile));
final int[] instantiatedClasses  = {-1}; /* so it would start at 0 */
loader.setControllerFactory((Class<?> controllerType) ->{
    if(controllerType == Controller.class){
        ++instantiatedClasses[0]; 
        return new Controller(instantiatedClasses[0]);
    }
});
Parent root = (Parent) fxmlLoader.load();

然而,这种方法的挑战在于,区分同一控制器类型的不同fxml实例仍然不容易。计算实例化类的数量是一种可行的方法,但与任何基于标识符的方法相比,它没有提供太多的控制。

支华池
2023-03-14

您可以从FXML文件中删除fx:controller=”“分配,并在加载过程中通过fxmloader分配控制器。

FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Your.fxml"));
fxmlLoader.setController(this);

try
{
    fxmlLoader.load();
}
catch (IOException exception)
{
    throw new RuntimeException(exception);
}

查看有关自定义组件的FXML简介部分。

 类似资料:
  • 这个动作被一个LoginController映射,成功登录后,用户回到相同的,但作为登录用户,并用欢迎消息迎接用户。 index.htm还有另一个名为itemform的表单,它允许用户将项目名称作为文本添加。此操作由itemController控制。 我的问题是我的LoginController和itemController都有相同的请求映射,因此我得到了这个错误: 创建名为“org”的bean时

  • 问题内容: 在此AngularJS代码中: 我有两个ng-app和两个控制器。但是似乎只有第一个有效。显示了姓名Jack,但没有显示Steve。为什么? 问题答案: 显示问题的JSFiddle在这里:http : //jsfiddle.net/DEnB2/ ng- app指令的自动初始化仅发生一次,但是您可以使用bootstrapping方法手动初始化其他模块。(请参阅:https : //doc

  • 我在web.php添加了以下路线,但它不起作用。 我的控制器如下所示,我正在使用Ajax发送数据,但收到的错误是Method not allowed exception。 Ajax代码----------------

  • 问题内容: 我有一个由一个控制器控制的fxml文件。我想将控制器分成多个部分,就像放置在一个控制器中会产生很长的代码一样。不幸的是,fx:controller只能放在根目录中。我对如何分离控制器有什么建议吗? 问题答案: 我建议创建自定义控件-使用几个较小的FXML文件,而不是一个大FXML文件。 这是本教程: http://docs.oracle.com/javafx/2/fxml_get_st

  • 我目前正在Spring Boot 2.4.0中编写一个应用程序,它需要侦听多个端口(具体来说是3个-但将来可能是4个)。这个想法是每个端口都提供不同的API供其他服务/应用程序连接到它。 所以,对于一个最小的工作示例,我会说我们有一个像这样的SpringBootApp: 现在,我想让它在3个不同的端口上监听,比如8080、8081和8082。所有人(!)对其中一个端口的请求,应由特定控制器“负责”