I'm using Java JDK 13, and FontAwesomeFX 11.
I have a FXML file which contains some FontAwesomeIconViews, but when loading the file into my controller I'm getting a javafx.fxml.LoadException. This is how the FXML file looks like:
<?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>
I'm getting the error on the first FontAwesomeIconView element (WINDOW_MINIMIZE).
I have suspicions it could be because FontAwesomeFX 11 expects FontAwesomeIconViews to be formatted in another way, but I'm not sure at all.
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)
Whenever you get a javafx.fxml.LoadException
, you have to read the whole stacktrace until the very end. It will show, usually at the end, the real cause for the exception.
Let's say you have this build.gradle
file, and your project is non-modular:
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' ]
}
and the FXML file with FontAwesomeIconView
:
<?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>
Then you run the project:
./gradlew clean run
and you get:
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)
If you stop reading there, you will think something is wrong with the line scene.fxml:7
which is the FontAwesomeIconView
one.
But if you keep reading the stacktrace:
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)
...
that last Caused by
says exactly the reason of the problem:
module javafx.graphics does not "opens javafx.css" to unnamed module @32ab3e54
This is due to the use of reflection in GlyphIcon
to access private API.
So now that you know the reason, all you have to do is provide the solution: In this case, we will add the requested --add-opens
to the jvm args in the build.gradle file:
run {
jvmArgs = ["--add-opens", "javafx.graphics/javafx.css=ALL-UNNAMED"]
}
Running again it will work.
Note 1
If you have a modular project, with a module-info descriptor like:
module hellofx {
requires javafx.controls;
requires javafx.fxml;
requires de.jensd.fx.fontawesomefx.fontawesome;
opens org.openjfx to javafx.fxml;
exports org.openjfx;
}
then you have to add instead:
run {
jvmArgs = ["--add-opens", "javafx.graphics/javafx.css=de.jensd.fx.fontawesomefx.commons"]
}
Note 2
If you are not using Gradle, you can still do the same.
For starters check the guide JavaFX 13 with Eclipse: https://openjfx.io/openjfx-docs/#IDE-Eclipse, and then choose your case.
If your case is non-modular from IDE, when you set the VM arguments like:
--module-path /path/to/javafx-sdk-13/lib --add-modules javafx.controls,javafx.fxml
all you need to do now is include the extra argument, like:
--module-path /path/to/javafx-sdk-13/lib --add-modules javafx.controls,javafx.fxml \
--add-opens javafx.graphics/javafx.css=ALL-UNNAMED
For other cases, the logic is the same.