3

I have been trying to get image resources to display on a GUI I am developing, but am having a difficult time getting them to display. I've come across other questions about loading resources such as java-swing-displaying-images-from-within-a-jar and images-will-not-work-in-a-jar-file, but they aren't working for me.

My issue appears to be the same as the first link, where images appear when run from Eclipse and don't appear when run from the command line using Jars. However the solution to those questions don't make the images appear.

The code I have for retrieving resources is:

public class R {

    public static final String resourcePackage = "path/to/image/package";

    /**
     * Returns the resource string that refers to the <code>resource</code> file
     * in the <code>path.to.image.package.png</code> package.
     * 
     * @param resource
     *            the file in the <code>png</code> package
     * @return the full resource string
     */
    public static String png(String resource) {
        return String.format("%s/png/%s", resourcePackage, resource);
    }

    public static ResizableIcon resizableIcon(String resource) {
        return ImageWrapperResizableIcon.getIcon(R.class.getClassLoader()
            .getResourceAsStream(resource), new Dimension(48, 48));
    }
}

I call it when generating the GUI

JCommandButton connect = new JCommandButton(i18ln.getString("ports"),
                R.resizableIcon(R.png("serial-port-32x32.png")));

A print statement indicates that the resource was found because R.class.getClassLoader().getResourceAsStream returns an instance of sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream.

I'm stumped. I have spent hours trying to figure this out, but could use some help. Any ideas?

FYI: I don't think it matters, but I am using Flamingo for my GUI.

EDIT: per Stefan's request

src/
    main/
        java/
            com.company.project (packages)
                R.java
                MyGui.java
        resources/
            com.company.project (packages)
                .png (package)
                    serial-port-32x32.png
                    (more images)
                .i18ln (package)
                    MyGui.properties

As for more code, I don't know what else I can provide that will be of much benefit for this question. All the code for retrieving resources and how I use that code is provided above. Was there something specific you were looking for?

UPDATE:

When I create a Jar using Eclipse and run it from the command line, the image resources display properly. When I create a Jar using Gradle, the images are not displayed. So there is something being done differently when generating the Jars that allows images resources to be accessed properly via the Eclipse Jar, but not the Gradle Jar. I opened a question on the Gradle forums with respect to this issue.

Community
  • 1
  • 1
E-rich
  • 9,243
  • 11
  • 48
  • 79
  • Have you checked whether the image is actually in the JAR. – Garrett Hall May 11 '12 at 13:04
  • @E-rich : Had you made one `Source Folder` while working with `Eclipse` to put your images inside that, if not have a look at my answer please, that might can guide you through it. – nIcE cOw May 11 '12 at 14:29

5 Answers5

3

Dependent on the environment in which your application is (Standalone, ApplicationServer), you will need to use the appropriate ClassLoader.

If you can have a utility class, Utils, you can try something like this:

/* Returns a instance of InputStream for the resource */
public static InputStream getResourceAsStream(String resource) 
                                                   throws FileNotFoundException {
    String stripped = resource.startsWith("/")?resource.substring(1):resource;
    InputStream stream = null;
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    if (classLoader != null) {
        stream = classLoader.getResourceAsStream(stripped);
    }
    if (stream == null) {
        stream = Utils.class.getResourceAsStream(resource);
    }
    if (stream == null) {
        stream = Utils.class.getClassLoader().getResourceAsStream(stripped);
    }
    if (stream == null) {
        throw new FileNotFoundException("Resource not found: " + resource);
    }
    return stream;
}

For use:

Utils.getResourceAsStream("com/company/project/png/serial-port-32x32.png");
Paul Vargas
  • 41,222
  • 15
  • 102
  • 148
  • Looked hopeful. Works in Eclipse, not from command line. From the command line, it returns a `sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream` instance. But then it throws a `javax.imageio.IIOException: Error reading PNG image data`. – E-rich May 11 '12 at 14:48
  • The `javax.imageio.IIOException: Error reading PNG image data` not is the root cause. – Paul Vargas May 11 '12 at 15:25
2

Here try this example HOW TO LOAD IMAGES TO YOUR ECLIPSE PROJECT. Hopefully this will explain things for you, More STEPS HERE

Don't use ClassLoader, thingy though, as described in this Java Doc , A quote from it states "All class loaders will search for a resource first as a system resource, in a manner analogous to searcing for class files."

Community
  • 1
  • 1
nIcE cOw
  • 24,468
  • 7
  • 50
  • 143
  • Both `src/main/java` and `src/main/resources` are source folders in Eclipse. Everything works fine in Eclipse; the issue is after I **jar** everything up and run from the commandline. The **.java** files and all resource files are included in the **.jar** file, but yet the images are not displayed. – E-rich May 11 '12 at 14:37
  • Yeah it's cause of the location they are in, that's why follow the steps I told you in that link, that way you can run your .jar with images in it. In Eclipse src is not your `Source Folder` you create that yourself, for `Application Resources` and you access them with a forward slash `/` – nIcE cOw May 11 '12 at 14:38
  • I receive a `javax.imageio.IIOException: Error reading PNG image data` thrown. I haven't been able to find much helpful information on that error. – E-rich May 11 '12 at 14:57
  • Are you sure, you followed the steps, if you did, then you be able to see the things that you placed inside the `Source Folder` to be copied to the bin folder as well, after you run it. Are you doing `Image image = ImageIO.read(getClass().getResource("/image/yourImage.extension"));` ? `where image is the folder that you created inside your Source Folder` – nIcE cOw May 11 '12 at 15:00
  • They are in the bin folder Eclipse creates, but that is not the issue. The issue is getting the image resources to display once the application is **jar**'d up and run outside of Eclipse. Yes, I am doing what you suggest in your comment. Although, I'm pretty sure that solution fails when resources are inside a **jar** (according to many other posts I've come across). – E-rich May 11 '12 at 15:02
  • I really dont' know, had you followed all the steps I had described, rebuild your project else from start and follow the steps, it ought to work, it always works, for me, I had made many jars like this and they all work. Try to access this link and get this [project](http://gagandeepbali.uk.to/gaganisonline/swing/buttondemo.zip), that will tell you the project structure. – nIcE cOw May 11 '12 at 15:07
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/11154/discussion-between-e-rich-and-nice-cow) – E-rich May 11 '12 at 15:18
2

Forget about the class loader, check the path. If feasible use getResource i.o. getResourceAsStream (question of style: more direct, and delivers null when not found).

As getResource(AsStream) is class based, the paths are relative, so try this:

R.class.getResource("/" + resource)
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
1

Create a resources package and place this class and your images in it:

public final class Resources {

    public static ImageIcon getImage(String filename) {
        URL resourceUrl = Resources.class.getResource(filename);
        return new ImageIcon(resourceUrl);
    }
}

Edit:

I have rebuild your structure with maven and flamingo (using your R class) and it works with these additions:

Change:

R.class.getClassLoader().getResourceAsStream(resource);

to:

R.class.getResource("png/"+resource);

I have used the maven-assemble-plugin to build the jar as described here.

Community
  • 1
  • 1
Stefan
  • 12,108
  • 5
  • 47
  • 66
  • Images display when run from Eclipse, but not from outside of Eclipse. – E-rich May 11 '12 at 13:52
  • Can you please post some more of your code and your project structure? – Stefan May 11 '12 at 13:58
  • Added my project structure. I don't know what more code I could provide for this issue; there isn't anything else being called for retrieving image resources. The localization **.properties** file is accessed via `ResourceBundle.getBundle("com.company.project.i18ln.MyGui")` and it works fine. – E-rich May 11 '12 at 14:16
0
URL imageurl = getClass().getResource("/images/serial-port-32x32.png");//relative path of the image as argument 
Image myPicture = Toolkit.getDefaultToolkit().getImage(imageurl);

Use this Image 'myPicture' as the first argument of ImageWrapperResizableIcon.getIcon method