【问题标题】:I can't load an image to change the icon of a window JavaFX我无法加载图像来更改窗口 JavaFX 的图标
【发布时间】:2020-05-22 09:18:17
【问题描述】:

我试图用 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"));
    }

}

ResourceLoader 类:

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

资源结构:

源代码 资源 图标.png

【问题讨论】:

    标签: java user-interface javafx window


    【解决方案1】:

    从您的代码看来 - 当您使用“文件:”协议时 - 您希望图像位于文件系统上的目录中。那么为什么不从文件而不是 URL 更改调用负载:

    File f = new File(getResourceLocation(), file);
    ImageIO.read(f)
    

    然后您可以通过调用 / 打印检查 Java 认为这些文件来自何处来解决目录位置问题:

    f.getAbsolutePath();
    f.exists();
    

    或者,如果这些图像与您的代码在同一个 jar 中,您应该使用 getClass().getResourceAsStream() 来定位 InputStream 以传递给 ImageIO.read(is)。

    【讨论】:

    • 我已经测试了你的方法,但它不起作用。我有这个错误:javax.imageio.IIOException: Can't read input file! F:\Workspace FireLauncherLib\resources\icon.png false 这很奇怪,因为该文件位于 F:\Workspace FireLauncherLib\resources\icon.png 但他没有阅读它。
    • 我加了System.out.println(f.getAbsolutePath()); System.out.println(f.exists());在控制台查看文件路径
    • 如果文件对象显示 f.exists() 为假,那么您的路径一定是错误的。检查您是否设置了正确的文件路径。您可以循环 f.getParentFile() 并检查每个级别。
    • 问题是代码中的路径对应的是真实路径。这真的很奇怪。我不明白为什么它不加载文件。
    • 在您解决 f.exists() 为假的原因之前,它不会加载文件,因为这证明路径错误,因此 java.io.FileNotFoundException。打印 f.getParentFile().exists() 等将帮助您查看哪个级别可能是错误的。祝你好运
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-12
    • 2019-11-04
    相关资源
    最近更新 更多