简体   繁体   中英

Can't load FXML in another package (JavaFX)

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

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".

Another thing to try for anyone experiencing this is to make sure that your fxml file is not empty. Open it in scenebuilder and drag an Anchor pane. That is what worked for me

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM