[SOLVED] Window / Game Icon Path

I managed to insert a WindowIcon, the Path is from the Repository, because from Source etc. this works. after a push my colleagues have an error that this file can not be read.

Path:
projects/droids/app/src/main/resources/Interface/helmet.png

public AppSettings getSettings() {
        final AppSettings settings = new AppSettings(true);
        try {
            settings.setIcons(new BufferedImage[]{
                    ImageIO.read(new File("Projekte/droids/app/src/main/java/pp/doom/helmet.png"))});
        }
        catch (IOException e) { //ignore error
        }
        settings.setTitle(windowTitle);
        settings.setResolution(resolutionWidth, resolutionHeight);
        settings.setFullscreen(fullScreen);
        settings.setUseRetinaFrameBuffer(useRetinaFrameBuffer);
        settings.setGammaCorrection(useGammaCorrection);
        return settings;
    }

would be very happy if someone can help me

Without the error I can’t be sure but a few things;

I would suggest not putting pngs in the java area, they should go in resources.

Even if the path was right that wouldn’t work when your app is packaged in a jar. You should load them from resources (which will work when it’s in a jar or run in an IDE). Here is how my game loads its icons

public static BufferedImage[] getIcons(){
    try {
        String iconsFolder = "Icons/";
        return new BufferedImage[] {
                ImageIO.read( getFileFromResourceAsStream("Icons/256.png" ) ),
                ImageIO.read( getFileFromResourceAsStream("Icons/128.png" )  ),
                ImageIO.read( getFileFromResourceAsStream("Icons/64.png" )  ),
                ImageIO.read( getFileFromResourceAsStream("Icons/32.png" )  )
        };
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

private static InputStream getFileFromResourceAsStream(String fileName) {

    ClassLoader classLoader = Icons.class.getClassLoader();
    InputStream inputStream = classLoader.getResourceAsStream(fileName);

    if (inputStream == null) {
        throw new IllegalArgumentException("file not found! " + fileName);
    } else {
        return inputStream;
    }

}

Note that those paths are relative to the root of resources. So in this example there is a folder within the resources folder called Icons that has 256.png etc in it

image.

Also, never do this

    try {
        //stuff
    }
    catch (IOException e) { //ignore error
    }

That error contains a bunch of useful stuff that might have helped you solve this (And really should have been included in your question). Never swallow an exception without at least 1 of these:

  • Logging it
  • Rethrowing it (where you include the original exception as a caused by, so new RuntimeException("message",e) for example)
  • Dealing with it in some other way (if you are expecting the exception and have some particular code that should run).

There are occasional rare exceptions but in general it’s a bad idea.

5 Likes

Thanks for your reply and your comment about the exception. I am still wondering why I can’t just take the resources folder i.e. the path from source root , but the path from repository root.

with Repository Path:

 public static BufferedImage[] getIcons(){
        try {
            return new BufferedImage[] {
                    ImageIO.read( new File("Projekte/droids/app/src/main/resources/Icons/helmet.png" ) ) 
            };
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

but it only works for me and not for the others

with Source Path:

 public static BufferedImage[] getIcons(){
        try {
            return new BufferedImage[] {
                    ImageIO.read( new File("Icons/helmet.png" ) ) 
            };
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

i get this error:

Exception in thread "main" java.lang.RuntimeException: javax.imageio.IIOException: Can't read input file!
	at pp.doom.DoomAppConfig.getIcons(DoomAppConfig.java:137)
	at pp.doom.DoomAppConfig.getSettings(DoomAppConfig.java:122)
	at pp.doom.DoomApp.<init>(DoomApp.java:81)
	at pp.doom.DoomApp.main(DoomApp.java:70)
Caused by: javax.imageio.IIOException: Can't read input file!
	at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1310)
	at pp.doom.DoomAppConfig.getIcons(DoomAppConfig.java:134)
	... 3 more

Caused by: javax.imageio.IIOException: Can't read input file!

Execution failed for task ':droids:app:DoomApp.main()'.
> Process 'command 'C:/Users/lukal/.jdks/temurin-18.0.2.1/bin/java.exe'' finished with non-zero exit value 1

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

the file is located in the resources folder
image

Probably need to add a slash at the start:

"/Icons/helmet.png"

What is a relative path relative to

I think this may be why you are finding it works but others are finding it doesn’t (It’s not the “real” problem but it is interesting).

A relative path will be relative to the directory you launched the application from (the working directory). And you don’t have to launch it from the gradle project root (or the repository root if those two aren’t the same) . Take this example project

image

public class DesktopTest{

    public static void main(String[] args) {
        boolean fileExists =  new File("randomFiles/AFile.txt").exists();
        System.out.println("Does the file exist? " + fileExists);
    }
}

Now if I run this with a normal run configuration with the working directory set as the gradle project root it all works fine

Does the file exist? true

But if I set a different working directory it doesn’t

Does the file exist? false

Possibly you have set your working directory to be somewhere other than the gradle project root and thats why it works for you?

What files make it to your users

All of the above was an aside because by the time these files get to your end users they won’t be files at all, they will either be within the jar (or in my case, in the folder randomFiles they won’t make it to the end user at all).

If I build a jar file to distribute to the end user

C:\Users\richa\Documents\Development\DesktopTest> gradle jar

Then a get a file DesktopTest.jar. If I now take that to another computer and try to run it I get:

C:\Users\richa\Documents>java -jar DesktopTest.jar
Does the file exist? false

Because the file AFile.txt is still on the development machine. It’s no use to an end user. Things within the resources folder automatically get bundled into the jar (yay!) but once they are in the jar they are not files, they are resources and cannot be referred to as files (this isn’t strictly speaking true, but for our purposes it is). There are special mecanisms for loading “things” from the resources folder. The JMonkeyEngine assetLoader is one, but would be overkill for this, the class loader is another. If I modify my project to move AFile.txt to within the resources folder

image

Then change the way I load the item to use the class loader

public class DesktopTest{

    public static void main(String[] args) throws IOException{

        ClassLoader classLoader = DesktopTest.class.getClassLoader();
        InputStream inputStream = classLoader.getResourceAsStream("AFile.txt");

        String aFileContent = new String(inputStream.readAllBytes());

        System.out.println("Whats in the file? " + aFileContent);
    }
}

Running this, even when compiled into a jar, succeeds and returns:

Whats in the file? Some text

You’ll notice my original example was using this approach to load icons, not using files. File is for user files really (in our case things like save games) not for things you bundle with your application (unless you go through a really painful distribution process of actually having them as files on the file system, not within the jar)

BufferedImage imageFromResources = ImageIO.read( getClass().getClassLoader().getResourceAsStream("Icons/256.png"))

1 Like

I have also tried this, unfortunately does not help but thanks! still same error message

Thank you, that helped me a lot!

1 Like