1

I have a problem with my Java class. Actually the code is correctly, but if I click the run-button there's a exception caused of the path of the image.

static Image currentBackground = new Image("Snake/Images/background_options.png", true);

And the compiler's message is:

Exception in thread "main" java.lang.ExceptionInInitializerError
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:122)
Caused by: java.lang.IllegalArgumentException: Invalid URL: Invalid URL or resource not found
    at javafx.scene.image.Image.validateUrl(Image.java:1100)
    at javafx.scene.image.Image.<init>(Image.java:624)
    at view.OptionsWindow.<clinit>(OptionsWindow.java:21)
    ... 3 more
Caused by: java.lang.IllegalArgumentException: Invalid URL or resource not found
    at javafx.scene.image.Image.validateUrl(Image.java:1092)
    ... 5 more

Process finished with exit code 1

Can anybody help me?

VGR
  • 40,506
  • 4
  • 48
  • 63
Viktoria
  • 533
  • 2
  • 7
  • 24
  • 2
    The message explicitly says `Invalid URL or resource not found`. This suggests you that the url specified is incorrect. Can you edit your question and add the project structure? – ItachiUchiha Oct 23 '15 at 14:39
  • 1
    Related question: [Where does javafx.scene.image.Image(“flower.png”) look for flower.png?](http://stackoverflow.com/questions/10575410/where-does-javafx-scene-image-imageflower-png-look-for-flower-png) – jewelsea Oct 23 '15 at 17:48

1 Answers1

8

The Image constructor is expecting the specification of a URL, not a file system path. Assuming you are bundling this image as part of your application, you will need to load that from the same place as your classes are loaded: probably a jar file in your final deployment, but perhaps from the file system during development.

The mechanism to get a URL representing a resource which is part of the application is to call getResource() on a Class or ClassLoader.

The exact way to do this depends on your project structure, which you haven't shown, but for example:

new Image(getClass().getResource("Snake/Images/background_options.png").toString(), true);

will load the image from a resource, specified relative to the current class, and

new Image(getClass().getClassLoader().getResource("Snake/Images/background_options.png").toString(), true);

will load the image from a resource specified relative to the class path.

In the event you pass a String that represents a relative URL (i.e. one with no scheme, such as file:, http:, or jar:), then the Image constructor will search on the class path for the resource. In other words

new Image("Snake/Images/background_options.png", true);

is equivalent to

new Image(getClass().getClassLoader().getResource("Snake/Images/background_options.png").toString(), true);

This seems slightly counter-intuitive (to me, at least), so I prefer to always specify a URL completely, or to retrieve one from getClass().getResource() or File.toURI().toURL() as appropriate.

James_D
  • 201,275
  • 16
  • 291
  • 322
  • I beg to differ on this answer. If you go through the Image source code, then you can find that Image internally loads the url from the `contextClassLoader`. The docs also explicitly states, "*If the passed string is not a valid URL, but a path instead, the Image is searched on the classpath in that case*". This means that `new Image("Snake/Images/background_options.png");` is perfectly fine and will load the image exactly as it should, as shown in your first example. – ItachiUchiha Oct 23 '15 at 15:47
  • Yeah, OK, that's true. So specifying a string with no URL scheme is equivalent to the second code block in the answer (relative to the class path). I find that counter-intuitive though: relative URL strings are usually considered relative to the "current resource". So I think explicitly getting the URL from somewhere makes more sense. – James_D Oct 23 '15 at 15:54
  • I do agree, this is weird! But, this is how the API is designed and whether to explicitly get the URL or leave it to the Image constructor is a choice that user has to make ;) – ItachiUchiha Oct 23 '15 at 16:13
  • Edited question to include this discussion. But I guess I'm not sure where you're really disagreeing with the answer: it is still searching the classpath and it is still creating a URL from the string. So, for example, `new Image("Snake/Images/background_options.png")` is still going to search a jar file, if the application is deployed that way. It just interprets it as a relative URL (and relative to the class path). – James_D Oct 23 '15 at 16:24
  • May be poor choice of words. I am not disagreeing, I was just making a point that (I felt) your answer was asking the OP to explicitly use `getClass().getResource(...)` or `getClass().getClassLoader.getResource(...)` and her way of loading the Image is incorrect. Now, with additional information, it is perfect. +1 – ItachiUchiha Oct 23 '15 at 16:29