您的方法存在问题
您没有格式正确的网址
new Image(String url) 将 url 作为参数。
空格不是 URL 的有效字符:
这就是为什么您的 x 字符串不是有效的 URL 并且不能用于构建图像的原因。
您需要提供 Image 构造函数识别的输入
请注意,它稍微复杂一些,因为从 Image javadoc 开始,url 参数可以不是直接的 url,但即便如此,它们都不匹配您要查找的内容。
如果将 URL 字符串传递给构造函数,它可以是
以下:
- 可以由上下文 ClassLoader 解析的资源的名称
对于这个线程
- 可以通过File解析的文件路径
- 一个 URL
可以通过 URL 解析并且存在协议处理程序
RFC
2397 除协议外,还支持 URL 的“数据”方案
为应用程序注册的处理程序。如果 URL 使用
“数据”方案,数据必须是 base64 编码并且 MIME 类型必须
要么是空的,要么是图像类型的子类型。
您假设资源位于文件系统中,但这并不总是有效
如果您将资源打包到 jar 中,那么这将不起作用:
Arrays.asList(
new File(
Thread.currentThread()
.getContextClassLoader()
.getResource(packageName)
.toURI()
).listFiles()
);
这不起作用,因为 jar 中的文件是使用jar: 协议而不是file: 协议定位的。因此,您将无法从 getResource 返回的 jar: 协议 URI 创建 File 对象。
推荐方法:使用 Spring
从 jar 中获取资源列表实际上是一件非常棘手的事情。从您链接的问题中,最简单的解决方案是使用
不幸的是,这意味着需要对 Spring 框架的依赖才能使用它,这对于这个任务来说完全是矫枉过正。 . .但是我不知道任何其他简单的强大解决方案。但至少你可以只调用 Spring 实用程序类,你不需要启动一个完整的 spring 依赖注入容器来使用它,所以你根本不需要知道任何 Spring 或承受任何 Spring 开销来做就这样吧。
所以,你可以这样写(ResourceLister 是我创建的一个类,以及 toURL 方法,请参见示例应用程序):
public List<String> getResourceUrls(String locationPattern) throws IOException {
ClassLoader classLoader = ResourceLister.class.getClassLoader();
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(classLoader);
Resource[] resources = resolver.getResources(locationPattern);
return Arrays.stream(resources)
.map(this::toURL)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
可执行示例
ResourceLister.java
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
public class ResourceLister {
// currently, only gets pngs, if needed, can add
// other patterns and union the results to get
// multiple image types.
private static final String IMAGE_PATTERN =
"classpath:/img/*.png";
public List<String> getImageUrls() throws IOException {
return getResourceUrls(IMAGE_PATTERN);
}
public List<String> getResourceUrls(String locationPattern) throws IOException {
ClassLoader classLoader = ResourceLister.class.getClassLoader();
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(classLoader);
Resource[] resources = resolver.getResources(locationPattern);
return Arrays.stream(resources)
.map(this::toURL)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
private String toURL(Resource r) {
try {
if (r == null) {
return null;
}
return r.getURL().toExternalForm();
} catch (IOException e) {
return null;
}
}
public static void main(String[] args) throws IOException {
ResourceLister lister = new ResourceLister();
System.out.println(lister.getImageUrls());
}
}
AnimalApp.java
import javafx.application.Application;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
public class AnimalApp extends Application {
private static final double ANIMAL_SIZE = 512;
// remove the magic seed if you want a different random sequence all the time.
private final Random random = new Random(42);
private final ResourceLister resourceLister = new ResourceLister();
private List<Image> images;
@Override
public void init() {
List<String> imageUrls = findImageUrls();
images = imageUrls.stream()
.map(Image::new)
.collect(Collectors.toList());
}
@Override
public void start(Stage stage) {
ImageView animalView = new ImageView();
animalView.setFitWidth(ANIMAL_SIZE);
animalView.setFitHeight(ANIMAL_SIZE);
animalView.setPreserveRatio(true);
Button findAnimalButton = new Button("Find animal");
findAnimalButton.setOnAction(e ->
animalView.setImage(randomImage())
);
VBox layout = new VBox(10,
findAnimalButton,
animalView
);
layout.setPadding(new Insets(10));
layout.setAlignment(Pos.CENTER);
stage.setScene(new Scene(layout));
stage.show();
}
private List<String> findImageUrls() {
try {
return resourceLister.getImageUrls();
} catch (IOException e) {
e.printStackTrace();
}
return new ArrayList<>();
}
/**
* Chooses a random image.
*
* Allows the next random image chosen to be the same as the previous image.
*
* @return a random image or null if no images were found.
*/
private Image randomImage() {
if (images == null || images.isEmpty()) {
return null;
}
return images.get(random.nextInt(images.size()));
}
public static void main(String[] args) {
launch(args);
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>resource-lister</artifactId>
<version>1.0-SNAPSHOT</version>
<name>resource-lister</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.version>5.7.1</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>17.0.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>LATEST</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
图片
放在 src/main/resources/img.
- 鸡.png
- cow.png
- 猪.png
- sheep.png
执行命令
为您的 JavaFX SDK 安装设置 VM 参数:
-p C:\dev\javafx-sdk-17.0.2\lib --add-modules javafx.controls