用于多个FXML的Java FX 1控制器 - 使用Singleton

时间:2015-10-21 09:11:00

标签: java controller fxml fxmlloader

我目前正在开发一个Java FX项目,我使用一个Controller用于多个FXML(请不要问为什么)! 我面临的问题是,每次新的FXML调用时,控制器都会创建一个新对象。 我希望一直使用同一个控制器,并尝试将Controller的构造函数实现为Singleton

public Controller(){}
private static Controller controller = null;

public synchronized static Controller getInstance() {
    if (controller == null)
        controller = new Controller();
    return controller;
}

这个策略给了我以下错误,因为似乎Java FX无法在不为每个FXML创建新构造函数的情况下工作。 还有其他办法吗?

这是我面临的错误: /Users/dwome/git/4winner/4win/target/classes/win/javafxscene.fxml:11

at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
at javafx.fxml.FXMLLoader.access$700(FXMLLoader.java:103)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:934)
at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:971)
at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:220)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:744)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3214)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3175)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3148)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3124)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3104)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3097)
at win.Main.start(Main.java:24)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$163(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$176(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$174(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$175(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)

Caused by: java.lang.IllegalAccessException: Class sun.reflect.misc.ReflectUtil can not access a member of class win.Controller with modifiers "private"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
at java.lang.Class.newInstance(Class.java:436)
at sun.reflect.misc.ReflectUtil.newInstance(ReflectUtil.java:51)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:927)
... 19 more

异常运行应用程序win.Main

2 个答案:

答案 0 :(得分:2)

我知道这个问题已经过时了,但是既然你没有发表评论就让它发挥作用了,这个问题似乎被看了很多,我会说我在面对同样的问题时所做的一切。

我用Darth Ninja在答案中说的话。

我的错误并不完全相同,但我认为无论如何它都可以工作,我有一个控制器用于多个FXML。

这是我的步骤:

  1. 从每个FXML中删除fx:controller="path.to.controller"
  2. 我创建了一个函数loadFXML

    private void loadFXML(String pathToFile){
        try{
            InputStream fxmlStream = getInstance().getClass().getResourceAsStream(path);
            FXMLLoader loader = new FXMLLoader();
            loader.setBuilderFactory(new JavaFXBuilderFactory());
            loader.setLocation(getInstance().getClass().getResource(path));
            loader.setController(instance);
            BorderPane panee = (BorderPane) loader.load(fxmlStream);
            Scene scene = new Scene(pane);
        }
    }
    
  3. 如您所见,我正在getInstance()loader.setController(instance);

    1. 实例化instance ...我做了一个“棘轮”的方式

      private static Controller instance;
      static{
           if (instance == null)}
                instance = new Controller();
           }
      }
      
    2. 可能对你的情况没有帮助,因为它是6个月前,但也可以帮助别人!

答案 1 :(得分:1)

使用FXMLLoader加载fxml。您可以通过setController()调用注入控制器。

或者,在加载fxmls时使用Controller Factory。您的控制器工厂可以返回相同的控制器对象