java - 我无法加载图像来更改窗口 JavaFX 的图标
问题描述
我试图用 JavaFx 制作一个带有图标的窗口,但它不起作用。我不知道为什么?我一直在使用 InputStream 进行测试,但我也遇到了错误。我使用 URL,它也不起作用。请帮忙
主类:
package fr.fireblaim.firelauncherlib_test;
import fr.fireblaim.firelauncherlib.WindowOptions;
import fr.fireblaim.firelauncherlib.graphics.Base;
import fr.fireblaim.firelauncherlib.utils.ResourceLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class Main extends Base {
private WindowOptions windowOptions = new WindowOptions(1280, 720, "Launcher Test", true, StageStyle.UNDECORATED);
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
Scene scene = new Scene(new LauncherPanel(windowOptions));
setupWindow(stage, scene, windowOptions, ResourceLoader.loadImage("icon.png"));
}
}
资源加载器类:
package fr.fireblaim.firelauncherlib.utils;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.image.Image;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
public class ResourceLoader {
private static String resourceLocation = "resources/";
public static Image loadImage(String file) {
try {
BufferedImage image = ImageIO.read(new URL( "file:" + getResourceLocation() + file));
return SwingFXUtils.toFXImage(image, null);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public static void setResourceLocation(String resourceLocation) {
ResourceLoader.resourceLocation = resourceLocation;
}
public static String getResourceLocation() {
return resourceLocation;
}
}
基类:
package fr.fireblaim.firelauncherlib.graphics;
import fr.fireblaim.firelauncherlib.WindowOptions;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.input.MouseEvent;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javax.swing.*;
import java.awt.*;
public abstract class Base extends Application {
private Point point = new Point();
public abstract void start(Stage stage) throws Exception;
protected void setupWindow(Stage stage, Scene scene, WindowOptions windowOptions) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
System.err.println("[FireLauncherLib] Can't setup the window:\n" + e);
}
stage.initStyle(windowOptions.getStageStyle());
stage.setResizable(false);
stage.setTitle(windowOptions.getTitle());
stage.setWidth(windowOptions.getWidth());
stage.setHeight(windowOptions.getHeight());
stage.setAlwaysOnTop(true);
stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
@Override
public void handle(WindowEvent event) {
Platform.exit();
System.exit(0);
}
});
if(windowOptions.isMovable()) {
scene.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
point.x = (int)(stage.getX() - event.getScreenX());
point.y = (int)(stage.getY() - event.getScreenY());
}
});
scene.setOnMouseDragged(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
stage.setX(event.getScreenX() + point.x);
stage.setY(event.getScreenY() + point.y);
}
});
}
stage.setScene(scene);
stage.show();
}
protected void setupWindow(Stage stage, Scene scene, WindowOptions windowOptions, Image icon) {
setupWindow(stage, scene, windowOptions);
stage.getIcons().clear();
stage.getIcons().add(icon);
}
}
我有这个错误:
javax.imageio.IIOException: Can't get input stream from URL!
at javax.imageio.ImageIO.read(ImageIO.java:1401)
at fr.fireblaim.firelauncherlib.utils.ResourceLoader.loadImage(ResourceLoader.java:17)
at fr.fireblaim.firelauncherlib_test.Main.start(Main.java:24)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$8(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$7(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$5(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$6(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at com.sun.glass.ui.gtk.GtkApplication.lambda$null$10(GtkApplication.java:245)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.FileNotFoundException: resources/icon.png (Aucun fichier ou dossier de ce type)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:93)
at sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:90)
at sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:188)
at java.net.URL.openStream(URL.java:1068)
at javax.imageio.ImageIO.read(ImageIO.java:1399)
... 11 more
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at javafx.stage.Stage$4.onChanged(Stage.java:696)
at com.sun.javafx.collections.TrackableObservableList.lambda$new$0(TrackableObservableList.java:45)
at com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:164)
at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
at javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:233)
at javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:482)
at javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541)
at javafx.collections.ObservableListBase.endChange(ObservableListBase.java:205)
at javafx.collections.ModifiableObservableListBase.add(ModifiableObservableListBase.java:155)
at java.util.AbstractList.add(AbstractList.java:108)
at fr.fireblaim.firelauncherlib.graphics.LauncherBase.setupWindow(LauncherBase.java:70)
at fr.fireblaim.firelauncherlib_test.Main.start(Main.java:24)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$8(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$7(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$5(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$6(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at com.sun.glass.ui.gtk.GtkApplication.lambda$null$10(GtkApplication.java:245)
at java.lang.Thread.run(Thread.java:748)
我使用 Intellij IDEA 2019.3.4 Ultimate
资源结构:
src资源图标.png
解决方案
从您的代码看来 - 当您使用“文件:”协议时 - 您希望图像位于文件系统上的目录中。那么为什么不从文件而不是 URL 更改调用负载:
File f = new File(getResourceLocation(), file);
ImageIO.read(f)
然后,您可以通过调用 / 打印检查 Java 认为这些文件来自何处来解决目录位置问题:
f.getAbsolutePath();
f.exists();
或者,如果这些图像与您的代码在同一个 jar 中,您应该使用 getClass().getResourceAsStream() 来定位 InputStream 以传递给 ImageIO.read(is)。
推荐阅读
- javascript - Vue 可拖动,只能在容器内拖动
- python-3.x - Python多处理具有不同参数的相同函数
- dependency-injection - 在 Autofac 中使用 RegistrationSource 自动注册
- node.js - 使用 axios 拦截器进行补丁请求
- css - -webkit-fill-available 的用途是什么?
- javascript - 打字稿错误 TS2554:预期 0 个参数,但得到 1 个。同时使用 useReducer 和 useContext 和 React
- python - 获取诗歌脚本端点
- ui-automation - 我们如何在空手道中按向下箭头键,然后按 Enter 键
- linux - grep 值大于
- c# - 我怎样才能让这个简单的 for 循环每秒运行一次?