Can't load FXML in another package (JavaFX)

房东的猫 提交于 2019-11-26 23:43:20

问题


For some reason I'm getting an error when I try to load an FXML which is in a different package:

MainApp.java"

FXMLLoader loader = new FXMLLoader();

            System.out.println("view folder: " + MainApp.class.getResource("view/RootLayout.fxml"));     // returns null
            loader.setLocation(MainApp.class.getResource("view/RootLayout.fxml"));

Folder structure:

Error message:

Exception in Application start method
java.lang.reflect.InvocationTargetException
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Exception in Application start method
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
        at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.IllegalStateException: Location is not set.
        at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2459)
        at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:2435)
        at checkmydigitalfootprint.MainApp.initRootLayout(MainApp.java:73)
        at checkmydigitalfootprint.MainApp.start(MainApp.java:55)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
        at java.base/java.security.AccessController.doPrivileged(Native Method)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
        at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
Exception running application checkmydigitalfootprint.MainApp

回答1:


I can tell you what works for me. Firstly, the FXML files should be considered resources rather than Java source files, so they're best placed into their own directory tree. Your source code is currently living in the /src/main/java tree, so your FXML files should be moved into the /src/main/resources tree, ideally into a subdirectory called fxml. (I also have a subdirectory called i18n which holds the resource bundles to define text labels in multiple languages.)

Once your FXML files are found under the path /src/main/resources/fxml you should be able to load them from your JavaFX controllers with something like this:

FXMLLoader loader = new FXMLLoader();
URL fxmlLocation = getClass().getResource("/fxml/main_screen.fxml");
loader.setLocation(fxmlLocation);
loader.setController(mainScreenController);
loader.setResources(ResourceBundle.getBundle("i18n/Text", new Locale("sv", "SE")));
Pane pane = loader.<Pane>load();
Scene scene = new Scene(pane);

(If the root element of your FXML file does not represent a Pane then you'll need to modify the line which calls the load() method, and replace Pane with the appropriate type.)

Note that the call to getResource(String) takes a path which begins with a forward-slash, and that represents the resource path root /src/main/resources/.

And also note that, bizarrely, the call to getBundle(String) does not start with a forward-slash, even though you're targeting exactly the same /src/main/resources/ path. I have to admit I can't explain why these two methods need to be treated slightly differently like this, but this code works to load both the "main_screen.fxml" file and the Swedish language resource bundle file "Text_sv_SE.properties".



来源:https://stackoverflow.com/questions/53699116/cant-load-fxml-in-another-package-javafx

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!