3

I have been unsuccessfully trying to display my image in my JavaFX application using fxml. My code:

...
<ImageView fitHeight="24" fitWidth="24"
    pickOnBounds="true" preserveRatio="true">
        <Image url="@res/icon.png"/>
</ImageView>
...

My project directory structure:
enter image description here

There is no error, but my image is not displaying. I think the image was loaded, but not displayed.
Is this possible? How can I check? If it is, shouldn't there be an error for it?

Infact, even if I give an incorrect name, there is no runtime error. So maybe not loaded?

I have also tried loading different images and changing the dimensions, nothing works.


I have tried:
  1. "/res/icon.png" -> Runtime error #1
  2. "res/icon.png" -> Lint error + Runtime error #1
  3. "/../res/icon.png" -> Lint error + Runtime error #1
  4. "../res/icon.png" -> Lint error + Runtime error #1
  5. "@/res/icon.png" -> Runtime error #2
  6. "@res/icon.png" -> Lint error (What I am using)
  7. "@/../res/icon.png" -> Lint error + Runtime error #2
  8. "@../res/icon.png" -> Lint error, no display

Runtime Error #1: Caused by: java.lang.IllegalArgumentException: Invalid URL: Invalid URL or resource not found

Runtime Error #2: Caused by: javafx.fxml.LoadException: Invalid resource: /res/icon.png not found on the classpath

(I know we shouldn't use .. or . in urls. I was just testing)


I have seen:
  1. Why does Image don't load in JavaFX which is exactly my configuration.
  2. How to show image using ImageView from where I got the proper way to link images in fxml. No error, but image not loading/displaying.
  3. ImageView does not work but I would like to do this in fxml only.
  4. Can't load JavaFX Image again fxml only.
  5. Cannot load Image in JavaFX again fxml only.
  6. Load Image to ImageView JavaFX again fxml only.
  7. JavaFX Image loading error I am not using CSS.
  8. JavaFX image loading in background and threads not what I'm interested in.
  9. How to determine correct path... very extensive, but what about fxml?

Edit: I recreated a duplicate of the original project and tried the troubleshooting following the comments.

The results (response to troubleshooting section):

  1. Proper image name: The name was valid, and the image properly deployed to out folder. But it was not recognized by the IDE and resulted in error or no display.

  2. Proper paths

    a) Absolute URLs

Interestingly, the getClass().getResource("/res/icon.png").getExternalForm() method gives:

 file:/C:/Users/Chander%20Shekhar/IdeaProjects/TestRes/out/production/TestRes/res/icon.png

and works. Not sure if the file: should be there. The getPath() method gives:

/C:/Users/Chander%20Shekhar/IdeaProjects/TestRes/out/production/TestRes/res/icon.png

and doesn't work (Runtime error#1). Removing the first / gave another error:

Caused by: java.lang.IllegalArgumentException: Invalid URL: unknown protocol: c

      b) Relative URLs

So I actually made a marker class in my res folder, and used ImageMarker.class.getResource("icon.png").toExternalForm() which gave

file:/C:/Users/Chander%20Shekhar/IdeaProjects/TestRes/out/production/TestRes/res/icon.png

Same as the first example, and works!

  1. Classpath: I also made sure I had the relative address from project root, the src folder (which I believe is the classpath root. Wrong?)

But in the end, all of this is still irrelevant, since I am using fxml. God!

Jaideep Shekhar
  • 808
  • 2
  • 7
  • 21
  • Where is your fxml file located? – Allan Juan Aug 29 '20 at 12:25
  • @AllanJuan my fxmls are in the `View` folder. Okay, I'll put them in the resources. Wow, it worked! :O Thanks! – Jaideep Shekhar Aug 29 '20 at 12:52
  • 1
    You have a solution, but I would check here whether or not the image file is being deployed, see “Troubleshooting” in the link you have in 9. – James_D Aug 29 '20 at 14:30
  • @James_D I read it, but I'll reread it. I was confused by the fact that there was no error, and yet no image displayed. And when I changed the name to something invalid, again no error. Why does one path give error, and one does not, even when image is not loaded? – Jaideep Shekhar Aug 29 '20 at 14:55
  • @JaideepShekhar I can’t give a complete answer to that, but note some errors are immediately detectable, and some aren’t. E.g. if the URL is simply not valid (malformed), the `FXMLLoader` can’t create a `URL` object and an exception can be thrown. OTOH there are certainly cases where that can’t be done - imagine you were using a `http:` url which didn’t exist, and background loading the image. The error wouldn’t happen immediately, so no exception could be thrown - the image’s `error` flag would just be set to `true`. Your cases are less clear, but exceptions aren’t always thrown for bad urls. – James_D Aug 29 '20 at 15:10
  • @JaideepShekhar For troubleshooting, I was just suggesting you needed to check the *build* folder, not the *source* folder, to make sure the image was actually being deployed (and to check where it was being deployed to). From the solution below, it seems pretty clear the issue was the IDE not deploying the `res` folder. – James_D Aug 29 '20 at 15:13
  • @James_D please see the edits in response to the troubleshooting. – Jaideep Shekhar Aug 30 '20 at 09:54
  • Also, is using `` in the fxml okay? As opposed to in the java code? Project directory structure as @Allan has described. – Jaideep Shekhar Aug 30 '20 at 10:01
  • Yes, if something can be done both in Java code or in FXML, it's up to you where you're going to do it. My only advice is to be consistent with whatever you choose. – Allan Juan Aug 30 '20 at 11:32

1 Answers1

4

I suggest you to use a resources folder, and put both your FXML and images in that folder. So you'd have this file structure:

src/
|-- main/
    | -- java/
    | -- resources/
         | -- fxml/screen.fxml
         | -- img/image.png

Then on screen.fxml you would do something like

<ImageView pickOnBounds="true" preserveRatio="true">
    <image>
        <Image url="@../img/image.png" />
    </image>
</ImageView>

That's how I organize my projects and it works just fine. CSS files will live in resources too, hope that helps.

PS: You have a res/ folder, but Java won't recognize it as a resource folder unless you acknowledge it. If you're on IntelliJ, you can right click it and then choose "Mark as resources root". If you use maven there are ways to declare it as your resource folder. Anyways, if you just rename it to resources/ it will be automatically considered as your resource folder.

Allan Juan
  • 2,048
  • 1
  • 18
  • 42