为什么我在加载 FXML 文件时收到 javafx.fxml.LoadException?



我正在使用Java JDK 13和FontAwesomeFX 11。

我有一个包含一些FontAwesomeIconViews的FXML文件,但是当将文件加载到我的控制器中时,我得到了一个javafx.fxml.LoadException。这是FXML文件的样子:

<?xml version="1.0" encoding="UTF-8"?>
<?import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<VBox id="window" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<BorderPane id="upper" fx:id="upper" prefHeight="50.0" prefWidth="800.0" stylesheets="@style.css">
<left>
<Label text="TEXT" BorderPane.alignment="CENTER">
<font>
<Font size="20.0" />
</font>
</Label>
</left>
<right>
<HBox prefHeight="100.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<children>
LINE 27           <FontAwesomeIconView glyphName="WINDOW_MINIMIZE" size="20" />
<FontAwesomeIconView glyphName="CLOSE" size="30" />
</children></HBox>
</right>
</BorderPane>
<AnchorPane id="body" prefHeight="554.0" prefWidth="800.0">
<children>
<TextField layoutX="326.0" layoutY="233.0" promptText="Usuario" />

<PasswordField layoutX="326.0" layoutY="276.0" promptText="Contraseña" />
<Button layoutX="353.0" layoutY="334.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="94.0" text="Acceder" />
<Label layoutX="326.0" layoutY="372.0" text="¿Ha olvidado la contraseña?" />
<FontAwesomeIconView glyphName="USER_CIRCLE" layoutX="350.0" layoutY="185.0" size="100" />
</children>
</AnchorPane>
</children>
</VBox>
</children>
</VBox>

我在第一个FontAwesomeIconView元素(WINDOW_MINIMIZE(上收到错误。

我怀疑这可能是因为FontAwesomeFX 11希望FontAwesomeIconViews以另一种方式格式化,但我完全不确定。

Error al cargar el archivo vista Login.fxml: javafx.fxml.LoadException: 
.../bin/view/login.fxml:27
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException: Root cannot be null
at javafx.graphics/javafx.scene.Scene.<init>(Scene.java:345)
at javafx.graphics/javafx.scene.Scene.<init>(Scene.java:236)
at controller.SplashController$SplashScreen$2.run(SplashController.java:78)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
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)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:830)

每当你得到一个javafx.fxml.LoadException,你必须读取整个堆栈跟踪直到最后。它通常会在最后显示异常的真正原因

假设您有此build.gradle文件,并且您的项目是非模块化的:

plugins {
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.8'
}
repositories {
jcenter()
}
dependencies {
implementation "de.jensd:fontawesomefx-commons:11.0"
implementation "de.jensd:fontawesomefx-fontawesome:4.7.0-11"
}
mainClassName = 'org.openjfx.MainApp'
javafx {
modules = [ 'javafx.controls', 'javafx.fxml' ]
}

和带有FontAwesomeIconView的 FXML 文件:

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.openjfx.FXMLController">
<FontAwesomeIconView glyphName="WINDOW_MINIMIZE" size="20" />
</VBox>

然后运行项目:

./gradlew clean run

你会得到:

java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
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: javafx.fxml.LoadException: 
/.../build/resources/main/org/openjfx/scene.fxml:7
at javafx.fxml/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2625)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2603)

如果你停止阅读那里,你会认为scene.fxml:7行有问题,这是FontAwesomeIconView行。

但是,如果您继续阅读堆栈跟踪:

java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
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: javafx.fxml.LoadException: 
/.../build/resources/main/org/openjfx/scene.fxml:7
at javafx.fxml/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2625)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2603)
...
Caused by: java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at javafx.fxml/com.sun.javafx.fxml.BeanAdapter.put(BeanAdapter.java:262)
...
Caused by: java.lang.reflect.InaccessibleObjectException: 
Unable to make javafx.css.ParsedValue javafx.css.CssParser.parseExpr(java.lang.String,java.lang.String) accessible: 
module javafx.graphics does not "opens javafx.css" to unnamed module @32ab3e54
...
at de.jensd.fx.glyphs.GlyphIcon.convert(GlyphIcon.java:248)
... 

最后Caused by准确地说明了问题的原因:

模块javafx.graphics不会"打开javafx.css"到未命名的模块@32ab3e54

这是由于在GlyphIcon中使用反射来访问私有 API。

因此,既然您知道了原因,您所要做的就是提供解决方案: 在这种情况下,我们将请求的--add-opens添加到 build.gradle 文件中的 jvm args 中:

run {
jvmArgs = ["--add-opens", "javafx.graphics/javafx.css=ALL-UNNAMED"]
}

再次运行它将起作用。

注1

如果你有一个模块化项目,带有模块信息描述符,如下所示:

module hellofx {
requires javafx.controls;
requires javafx.fxml;
requires de.jensd.fx.fontawesomefx.fontawesome;
opens org.openjfx to javafx.fxml;
exports org.openjfx;
}

然后你必须添加:

run {
jvmArgs = ["--add-opens", "javafx.graphics/javafx.css=de.jensd.fx.fontawesomefx.commons"]
}

注2

如果您没有使用 Gradle,您仍然可以执行相同的操作。

对于初学者,请查看指南JavaFX 13 with Eclipse: https://openjfx.io/openjfx-docs/#IDE-Eclipse,然后选择您的案例。

如果您的情况不是来自 IDE 的模块化,则在设置 VM 参数时,如下所示:

--module-path /path/to/javafx-sdk-13/lib --add-modules javafx.controls,javafx.fxml

您现在需要做的就是包含额外的参数,例如:

--module-path /path/to/javafx-sdk-13/lib --add-modules javafx.controls,javafx.fxml 
--add-opens javafx.graphics/javafx.css=ALL-UNNAMED

对于其他情况,逻辑是相同的。

最新更新