You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Maven模块化JavaFX项目资源加载异常求助

JavaFX模块化项目中资源(图片/字体)加载问题解决方法

问题背景

在IntelliJ IDEA开发基于Maven的JavaFX模块化项目时,尝试从src/main/java/com/example/App.java加载src/main/resources/images/logo.png图片与src/main/resources/fonts/pikzel.ttf字体,初始使用根路径URL(如/images/logo.png)加载时直接崩溃,解决图片加载后字体加载仍抛出空指针异常,需要简便的相对URL加载方案。

初始尝试代码

Image logo = new Image("/images/logo.png");
ImageView logoView = new ImageView(logo);
logoView.setPreserveRatio(true);
logoView.setFitHeight(100);

Label titleLabel = new Label("Regirocko");
Font pikzel = Font.loadFont("/fonts/pikzel.ttf", 36);
titleLabel.setFont(pikzel);

已完成的图片加载解决

项目为模块化结构,通过在module-info.java中添加以下配置开放图片所在包:

opens atzelord.regirocko.images;

并修改图片加载代码为:

Image logo = new Image("atzelord/regirocko/images/logo.png");

图片加载恢复正常,但字体加载采用相同方式时失败。

字体加载失败的代码与异常

字体加载代码:

Font pikzel = Font.loadFont("atzelord/regirocko/fonts/pikzel.ttf", 36);

抛出的异常信息:

C:\Users\Joan.jdks\openjdk-19.0.1\bin\java.exe -javaagent:C:\Users\Joan\AppData\Local\JetBrains\Toolbox\apps\IDEA-C\ch-0\231.8109.175\lib\idea_rt.jar=51977:C:\Users\Joan\AppData\Local\JetBrains\Toolbox\apps\IDEA-C\ch-0\231.8109.175\bin -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath C:\Users\Joan.m2\repository\org\openjfx\javafx-controls\19\javafx-controls-19.jar;C:\Users\Joan.m2\repository\org\openjfx\javafx-graphics\19\javafx-graphics-19.jar;C:\Users\Joan.m2\repository\org\openjfx\javafx-base\19\javafx-base-19.jar;C:\Users\Joan.m2\repository\org\openjfx\javafx-fxml\19\javafx-fxml-19.jar;C:\Users\Joan.m2\repository\org\openjfx\javafx-fxml\19\javafx-fxml-19-win.jar -p "C:\Users\Joan.m2\repository\org\openjfx\javafx-base\19\javafx-base-19-win.jar;C:\Users\Joan.m2\repository\org\openjfx\javafx-controls\19\javafx-controls-19-win.jar;C:\Users\Joan.m2\repository\org\openjfx\javafx-graphics\19\javafx-graphics-19-win.jar;C:\Users\Joan\Documents\Mes documents\Java\regirocko\target\classes" -m atzelord.regirocko/atzelord.regirocko.App
Exception in Application start method
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:119)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at javafx.graphics@19/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:465)
at javafx.graphics@19/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:364)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1081)
Caused by: java.lang.RuntimeException: Exception in Application start method
at javafx.graphics@19/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:901)
at javafx.graphics@19/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:196)
at java.base/java.lang.Thread.run(Thread.java:1589)
Caused by: java.lang.NullPointerException: 无法调用"javafx.scene.text.Font.getNativeFont()",因为""为null
at javafx.graphics@19/javafx.scene.text.Font$1.getNativeFont(Font.java:68)
at javafx.graphics@19/com.sun.javafx.scene.text.FontHelper.getNativeFont(FontHelper.java:46)
at javafx.controls@19/com.sun.javafx.scene.control.skin.Utils.computeTextHeight(Utils.java:138)
at javafx.controls@19/javafx.scene.control.skin.LabeledSkinBase.computeMinLabeledPartHeight(LabeledSkinBase.java:841)
at javafx.controls@19/javafx.scene.control.skin.LabeledSkinBase.computeMinHeight(LabeledSkinBase.java:311)
at javafx.controls@19/javafx.scene.control.Control.computeMinHeight(Control.java:499)
at javafx.graphics@19/javafx.scene.Parent.minHeight(Parent.java:1062)
at javafx.graphics@19/javafx.scene.layout.Region.minHeight(Region.java:1571)
at javafx.graphics@19/javafx.scene.layout.Region.computeChildMinAreaHeight(Region.java:1981)
at javafx.graphics@19/javafx.scene.layout.Region.getMaxAreaHeight(Region.java:2262)
at javafx.graphics@19/javafx.scene.layout.Region.computeMaxMinAreaHeight(Region.java:2131)
at javafx.graphics@19/javafx.scene.layout.HBox.computeMinHeight(HBox.java:422)
at javafx.graphics@19/javafx.scene.Parent.minHeight(Parent.java:1062)
at javafx.graphics@19/javafx.scene.layout.Region.minHeight(Region.java:1571)
at javafx.graphics@19/javafx.scene.layout.Region.computeChildMinAreaHeight(Region.java:1981)
at javafx.graphics@19/javafx.scene.layout.VBox.getAreaHeights(VBox.java:447)
at javafx.graphics@19/javafx.scene.layout.VBox.computeContentHeight(VBox.java:529)
at javafx.graphics@19/javafx.scene.layout.VBox.computeMinHeight(VBox.java:407)
at javafx.graphics@19/javafx.scene.Parent.minHeight(Parent.java:1062)
at javafx.graphics@19/javafx.scene.layout.Region.minHeight(Region.java:1571)
at javafx.graphics@19/javafx.scene.layout.Region.computeChildPrefAreaHeight(Region.java:2046)
at javafx.graphics@19/javafx.scene.layout.VBox.getAreaHeights(VBox.java:451)
at javafx.graphics@19/javafx.scene.layout.VBox.layoutChildren(VBox.java:562)
at javafx.graphics@19/javafx.scene.Parent.layout(Parent.java:1207)
at javafx.graphics@19/javafx.scene.Scene.doLayoutPass(Scene.java:592)
at javafx.graphics@19/javafx.scene.Scene.preferredSize(Scene.java:1786)
at javafx.graphics@19/javafx.scene.Scene$2.preferredSize(Scene.java:409)
at javafx.graphics@19/com.sun.javafx.scene.SceneHelper.preferredSize(SceneHelper.java:66)
at javafx.graphics@19/javafx.stage.Window$12.invalidated(Window.java:1163)
at javafx.base@19/javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:110)
at javafx.base@19/javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:145)
at javafx.graphics@19/javafx.stage.Window.setShowing(Window.java:1239)
at javafx.graphics@19/javafx.stage.Window.show(Window.java:1254)
at javafx.graphics@19/javafx.stage.Stage.show(Stage.java:277)
at atzelord.regirocko/atzelord.regirocko.App.start(App.java:20)
at javafx.graphics@19/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:847)
at javafx.graphics@19/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:484)
at javafx.graphics@19/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:457)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at javafx.graphics@19/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:456)
at javafx.graphics@19/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics@19/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics@19/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
... 1 more
Exception running application atzelord.regirocko.App

Process finished with exit code 1


解决方法

一、模块化项目资源加载核心规则

Java模块化项目中,资源默认被封装在模块内部,直接使用根路径(/xxx)无法访问,必须通过模块资源API或模块路径+资源路径的方式加载,同时需要在module-info.java中开放资源所在的包。

二、字体加载的正确实现

  1. 开放字体所在包:在module-info.java中添加配置
opens atzelord.regirocko.fonts;
  1. 使用类资源API加载字体:通过getClass().getResource()获取资源URL,避免路径拼写错误,确保资源能被正确找到
// 非静态方法中加载
URL fontUrl = getClass().getResource("/fonts/pikzel.ttf");
Font pikzel = Font.loadFont(fontUrl.toExternalForm(), 36);

// 静态方法中加载,替换为对应类名
URL fontUrl = App.class.getResource("/fonts/pikzel.ttf");
Font pikzel = Font.loadFont(fontUrl.toExternalForm(), 36);
  1. 验证资源存在:确认Maven编译后,target/classes/fonts/pikzel.ttf文件存在,若不存在需检查Maven资源配置或文件路径是否正确。

三、通用简便的资源加载方案

不管是图片还是字体,都可以用以下统一方式加载,避免路径问题:

// 加载图片
Image image = new Image(getClass().getResource("/路径/文件名").toExternalForm());

// 加载字体
Font font = Font.loadFont(getClass().getResource("/路径/文件名").toExternalForm(), 字号);

同时在module-info.java中开放对应资源包:

opens atzelord.regirocko.images;
opens atzelord.regirocko.fonts;

内容的提问来源于stack exchange,提问作者Atzelord

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 15:12:03