Всякий раз, когда вы получаете 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' ]
}
и файл FXML с 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>
Затем вы запускаете проект:
./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
к аргументам jvm в файле build.gradle:
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"]
}
Note 2
Если вы не используете Gradle, вы все равно можете сделать то же самое.
Для начала проверьте руководство JavaFX 13 с 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
Для других случаев логика та же.