【发布时间】:2018-11-23 17:42:05
【问题描述】:
问题
当应用程序被打包为 Jar 文件时,我应该怎么做才能在我的 JavaFX 应用程序中加载资源?
背景
该应用程序是 IntelliJ IDEA 中的一个 Maven 项目。直接从 IntelliJ 运行应用程序适用于下面描述的所有情况,但我从项目构建的 jar 文件大多无法加载资源(图像和字体)。
项目目录树
application
├── .idea
├── out
├── src
| ├── main
| | ├── java
| | | ├── META-INF
| | | └── Main.java
| | └── resources
| | ├── images
| | | ├── img1.jpg
| | | └── img2.png
| | ├── fonts
| | | └── font.ttf
| | └── stylesheet.css
| └── test
├── target
├── application.iml
└── pom.xml
加载图片的工作方式如下:
Image img1 = new Image(this.getClass().getResource("images/img1.jpg").toString());
Image img2 = new Image(this.getClass().getResource("images/img2.png"));
但由于我实际上想加载图像文件夹中的所有图像而不对它们的名称进行硬编码,所以我一直在这样做:
File dir = new File(this.getClass().getResource("images").getFile());
List<File> imageFiles = new ArrayList<>(Arrays.asList(dir.listFiles()));
List<Image> images = new ArrayList<>();
for (int i = 0; i < imageFiles.size(); i++) {
images.add(new Image("images/" + imageFiles.get(i).getName()));
}
当应用程序被打包成 jar 文件并在第 2 行导致 NullPointerException 时,这不起作用。事实证明 dir.listFiles() 返回 null 而 dir.exists() 返回 false。
加载字体我尝试了两种方式。像这样在stylesheet.css:
@font-face {
font-family: 'Font';
src: url('fonts/font.ttf');
}
或者像这样作为Main的start方法的第一行:
Font.loadFont(getClass().getResourceAsStream("fonts/font.ttf"), 20);
在任何一种情况下,我都通过样式表应用字体。从 IntelliJ 中运行应用程序时,这两种情况都有效,但在运行 jar 时均无效。第一种方法打印错误信息
Jun 14, 2018 4:21:47 AM com.sun.javafx.css.StyleManager loadStylesheetUnPrivileged
INFO: Could not load @font-face font [jar:file:/D:/path/in/file/system/java/application/out/artifacts/application_jar/application.jar!/fonts/font.ttf]
第二种方法静默失败。
我做了什么和其他信息
我正在通过Build -> Build Artifacts... 在 IntelliJ 中构建 jar。 resources 目录在 IntelliJ 中标记为 Resources Root,这是我的 pom.xml。
生成的 jar 文件确实包含我认为它应该具有的所有资源。也就是说,它有以下目录树:
application.jar
├── images
| ├── img1.jpg
| └── img2.png
├── fonts
| └── font.ttf
├── META-INF
├── Main.class
└── stylesheet.css
在发表这篇文章之前我咨询过的资源是Apache Maven Archiver、IntelliJ Working With Artifacts、StackOverflow NullPointerException When...、StackOverflow JavaFX and maven... 和几个类似的问题。他们中的许多人解决了NullPointerException: Location is required 问题,这似乎是在从 xml 加载 JavaFX 布局时发生的,我没有这样做,也不是我得到的错误。
请注意,我以前几乎没有使用过 Maven,只有文件流、类加载器等的基本概念以及一些 JavaFX 经验。
【问题讨论】:
-
你试过
this.getClass().getResource("yourpath").toExternalForm()吗? -
@Adi 接受的答案适用于加载图像,谢谢!我觉得很奇怪,似乎没有更好的方法可以在不知道资源名称的情况下在 jar 中加载资源。
标签: java maven intellij-idea resources embedded-resource