问题描述
出于某种原因,当我尝试加载位于不同包中的 FXML 时出现错误:
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"));
文件夹结构:
错误信息:
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
推荐答案
我可以告诉你什么对我有用.首先,FXML 文件应该被视为资源而不是 Java 源文件,因此最好将它们放在自己的目录树中.您的源代码当前位于 /src/main/java
树中,因此您的 FXML 文件应该移动到 /src/main/resources
树中,最好是移动到名为 fxml
的子目录.(我还有一个名为 i18n
的子目录,其中包含用于定义多种语言文本标签的资源包.)
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.)
在路径 /src/main/resources/fxml
下找到您的 FXML 文件后,您应该能够使用以下内容从 JavaFX 控制器加载它们:
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);
(如果 FXML 文件的根元素不代表 Pane
,那么您需要修改调用 load()
方法的行,并替换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.)
请注意,对 getResource(String)
的调用采用以正斜杠开头的路径,该路径表示资源路径根 /src/main/resources/
.
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/
.
还要注意,奇怪的是,对 getBundle(String)
的调用不是以正斜杠开头,即使您的目标完全相同 /src/main/resources/ 路径.我不得不承认我无法解释为什么需要像这样稍微不同地对待这两种方法,但是这段代码可以同时加载main_screen.fxml"文件和瑞典语资源包文件Text_sv_SE.properties".
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".
这篇关于无法在另一个包中加载 FXML (JavaFX)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!