Where should I place resource-files like images ?

A

Arne Styve

Hi,

I'm building an application where I want to use buttons (JButton) with
images loaded from files (.GIF-files).

At the moment, I create the ImageIcon's to use like this:
disconIcon = new ImageIcon("resources/images/discon.gif");
lightOnIcon = new ImageIcon("resources/images/LightOn.gif");
lightOffIcon = new ImageIcon("resources/images/LightOff.gif");

and then use the setIcon()-method of the button to set the Icon.

This works, but I'm not quite confortable with it.
What is the best strategy for placing image-files so that they will always
be found, both when running the application from within Eclipse, and when
creating a JAR of the application for distribution ? When creating a JAR, I
would like the image-files to be packed within the JAR. How should I refere
to the image-files to ensure they will always be found independent of where
my code/JAR-file is installed on the target ?

Regards
Arne
 
C

Cyril

Hi,

Arne Styve a écrit :
What is the best strategy for placing image-files so that they will always
be found, both when running the application from within Eclipse, and when
creating a JAR of the application for distribution ? When creating a JAR,I
would like the image-files to be packed within the JAR. How should I refere
to the image-files to ensure they will always be found independent of where
my code/JAR-file is installed on the target ?

Use getClass().getClassLoader().getResource(), this way:

disconIcon = new
ImageIcon(getClass().getClassLoader().getResource("resources/images/discon.gif"));

The images must be in your class path with the correct path (here
resources/images).

Cheers,

Cyril
 
T

Thomas Weidenfeller

Arne said:
What is the best strategy for placing image-files so that they will always
be found, both when running the application from within Eclipse, and when
creating a JAR of the application for distribution ?

You locate the image data via the class loader. See Class.getResource()
to get a URL, and use that URL to load the image.

Spend a minute or two to learn about the difference between specifying
an absolute or relative resource location from the API documentation of
getResource().
When creating a JAR, I
would like the image-files to be packed within the JAR. How should I refere
to the image-files to ensure they will always be found independent of where
my code/JAR-file is installed on the target ?

See above. getResource() uses a class loader. The default class loader
is typically one of type URLClassLoader or similar and it resolves
locations using the class path. Entries in the class path can be
directories or jars. If the jar with the icons is in the class path
(and(!) you provide the correct resource name string) the icons are
found in the jar.

/Thomas
 
T

Thomas Weidenfeller

Cyril said:
disconIcon = new
ImageIcon(getClass().getClassLoader().getResource("resources/images/discon.gif"));

disconIcon = new
ImageIcon(getClass().getResource("resources/images/discon.gif"));

or in static context or if you want to avoid subclassing changing the
lookup of relative resources:

disconIcon = new
ImageIcon(<the-class-name>.class.getResource("resources/images/discon.gif"));


1) Class has an own getResource() method which does the work. No need to
dereference the ClassLoader first.

2) Class.getResource() can lock up resources relatively to the current
class, ClassLoader.getResource() doesn't.

/Thomas
 
A

Arne Styve

Hi Thomas (and Cyril),

Thanks for your answers. I'll try it out.

Do you have any strategies regarding where you place resources like this ?
Do you put them in a seperate directory, like I've suggested, or do you
place these types of files in the same directory as the classes that uses
them ?

Regards Arne
 
C

Cyril

Hi,

Thomas Weidenfeller a écrit :
1) Class has an own getResource() method which does the work. No need to
dereference the ClassLoader first.

2) Class.getResource() can lock up resources relatively to the current
class, ClassLoader.getResource() doesn't.

Thanks for that tip. Always eager to learn ;-)

Cheers,

Cyril
 
T

Thomas Weidenfeller

Arne said:
Do you have any strategies regarding where you place resources like this ?
Do you put them in a seperate directory, like I've suggested, or do you
place these types of files in the same directory as the classes that uses
them?

It depends :)

If you want, for example, build a self-contained component (some
JavaBean etc.), it would make sense to have resources like icons
relatively to the class, probably in a subdirectory "resources".

If you have, for example, application-wide resources like application
icons, it would make sense to have them in some absolute location, or
relative to some main class - which would then, from an application's
point of view, also be some kind of absolute location.

/Thomas


BTW: Consider changing your quoting style. Many people on Usenet will
already ignore you for posting the response before the quotation. It
belongs after the quotation.
 
A

Arne Styve

Thomas Weidenfeller said:
See above. getResource() uses a class loader. The default class loader is
typically one of type URLClassLoader or similar and it resolves locations
using the class path. Entries in the class path can be directories or
jars. If the jar with the icons is in the class path (and(!) you provide
the correct resource name string) the icons are found in the jar.

/Thomas

I've studied the article at
http://java.sun.com/j2se/1.5.0/docs/guide/lang/resources.html and I also
found one at http://java.sun.com/docs/books/tutorial/uiswing/misc/icon.html.
The latter one was quite detailed and good. BUT I still have the same
problem. I've tried placing the images as subdirectories/packages under the
package where the class is defined that uses the images, and I've tried
placing the images at the root of the packages. It always work when I run my
application from within NetBeans or Eclips, but as soon as I create a JAR
with both the classes and the images, I cannot locate the image-files. I've
followed the details in the ICON-tutorial mentioned above, but still no
success. Is there a way to print the path from where getResource() starts to
search from ?

-Arne

PS! Thanks for your patience..
 
O

opalpa

Is there a way to print the path from where getResource() starts to
search from ?


say you got:

package com.arne.util;
class Goods {
....
Goods.class.getResource("pic.png");
Goods.class.getResource("pix/a.png");
....
}

getResource looks from where the Goods.class file is. So if that file
is in directory $D then the first getResource gets $D/pic.png and the
second getResource gets $D/pix/a.png .

Opalinski
(e-mail address removed)
http://www.geocities.com/opalpaweb/
 
A

Arne Styve

say you got:

package com.arne.util;
class Goods {
...
Goods.class.getResource("pic.png");
Goods.class.getResource("pix/a.png");
...
}

getResource looks from where the Goods.class file is. So if that file
is in directory $D then the first getResource gets $D/pic.png and the
second getResource gets $D/pix/a.png .

Opalinski
(e-mail address removed)
http://www.geocities.com/opalpaweb/

Thanks Opalinksi. I've got this to work. But when I create a JAR file with
the class Goods in the package com.arne.util, and with the pix/a.png file
included, I thought I still could use the same getResource("pix/a.png") when
I start the application from the JAR-file like the following:

c:\SomeDir\AppDir>java -cp Goods.jar Goods

The Goods.jar file is in the c:\SomeDir\AppDir directory.

But this does not work.
Here is the code that gets the resource:

java.net.URL imgURL =
ProjectorButton.class.getResource("discon.gif");
System.out.println("imgURL: " + imgURL);

The class ProjectorButton is in the package no.hials.ProjectorControl.gui.
The file "discon.gif" is placed at the root of the src-directory. When I use
NetBeans, the IDE creates a "build/classes" directory in which the
..class-files end up in a directorystructure simelar to the package
structure. The GIF-files are copied to the "build/classes" directory. When
run from Netbeans this works fine. NetBeans also builds a JAR from the files
in the "build/classes" directory, including the gif-files. The JAR file is
placed in a new directory, named "dist" which is at the same level as the
"build" directory. When I then open the CMD-window, and type:

.....\dist>java -cp ProjectorManager.jar
no.hials.ProjectorControl.gui.ProjectorControl

the application starts just fine, but the "imgURL" ends up beeing "null",
and I'm not able to understand why.

Any ideas, now that you've got some more details ? There must be something
I'm missing out on here....

-Arne
 
O

opalpa

Take a peek at the contents of Goods.jar. One way to look at contents
is to:
"jar -ft Goods.jar"

Does discon.gif file appear in the same directory as
ProjectorButton.class file? Does it appear at all?
The GIF-files are copied to the "build/classes" directory.

Are they copied to correct directory? Are they put inside jar?

Opalinski
(e-mail address removed)
http://www.geocities.com/opalpaweb/
 
O

opalpa

I want to clarify:
The GIF-files are copied to the "build/classes" directory.

The gif needs be in "build/classes/no/hials/ProjectorControl/gui"
because that is where ProjectorButton.class is.

The gif being in "build/classes" is not the right spot.

After you assure this, assure the same is true about contents of jar.

Opalinski
(e-mail address removed)
http://www.geocities.com/opalpaweb/
 
A

Arne Styve

I want to clarify:


The gif needs be in "build/classes/no/hials/ProjectorControl/gui"
because that is where ProjectorButton.class is.

Yes, I've tried putting them there. When in this directory and running from
within NetBeans/Eclipse, it works fine.
The gif being in "build/classes" is not the right spot.

This works fine if I use .getResource("/discon.gif"); and use the
ClassLoader instead of ProjectorControl.class.getSource().
After you assure this, assure the same is true about contents of jar.

Yepp, when I do a "jar -ft" on my JAR-file, I find:

no/hials/ProjectorControl/gui/LightOff.GIF
no/hials/ProjectorControl/gui/LightOn.GIF
no/hials/ProjectorControl/gui/ProjectorButton.class

The funny thing is, however, when I place the .GIF-files directly on the
"dist"-directory (not in the JAR-file), same directory as the JAR-file is
in, and I use the "/discon.gif", i.e. absolute reference, it works fine. It
seems like the getResource()-method does not check the JAR-file at all.....

Thanks for trying to help me out here. I'm really banging my head against a
brick wall here....

-Arne
 
O

opalpa

Yepp, when I do a "jar -ft" on my JAR-file, I find:
no/hials/ProjectorControl/gui/LightOff.GIF
no/hials/ProjectorControl/gui/LightOn.GIF
no/hials/ProjectorControl/gui/ProjectorButton.class

What about discon.gif? Also, maybe uppercase counts? I don't know
cause I always match case.
This works fine if I use .getResource("/discon.gif"); and use the
ClassLoader instead of ProjectorControl.class.getSource().

Are you using ProjectControl.class.getResource() or
ProjectButton.class.getResource()? They will look things up in
different directories. When using either one you don't want the "/"
prefixing the paths.

I assure you this stuff works, go through your code carefully, make a
simple example.

Opalinski
(e-mail address removed)
http://www.geocities.com/opalpaweb/
 
A

Arne Styve

What about discon.gif? Also, maybe uppercase counts? I don't know
cause I always match case.

Case doesn't seam to matter, since it works when running from classes
(NetBeans/Eclipse runs directly from the "build" directory). But I'll make
sure I use the same case.
Are you using ProjectControl.class.getResource() or
ProjectButton.class.getResource()? They will look things up in
different directories. When using either one you don't want the "/"
prefixing the paths.

I've tried using both ProjectorButton, ProjectorControl, and the
ClassLoader.getSystemClassLoader().getResource()

and printed the resulting imgURL, and seen how this makes a different. It
all works as long as I dont run it from my JAR file.......
I assure you this stuff works, go through your code carefully, make a
simple example.

I thought so too. I'll follow your advise and create a small example and run
it through the test.

Thanks for trying to help me out. Your support has been invaluable :)

-Arne
 
R

Roedy Green

This works, but I'm not quite confortable with it.

the thing I don't like is the way you don't find out till run time if
image is missing. I want a way making sure all images I use are in
there and no deadwood.

see http://mindprod.com/jgloss/cramfull.html

Cramfull ensures all resources included in jar. It does it by
converting your resoures into class files, that tools like GenJar can
find using dependencies.

See http://mindprod.com/jgloss/dependencies.html
http://mindprod.com/jgloss/genjar.html

there should be some less drastic and memory-hungry solution that ends
up with a traditional jar with resources.
 
O

opalpa

Case doesn't seam to matter, since it works when running from classes
(NetBeans/Eclipse runs directly from the "build" directory). But I'll make
sure I use the same case.

I googled whether case matters. Case does not matter when loading from
windows file system. Case does matter when loading from jar. Perhaps
this is the issue. I did not write any experimets.

Opalinski
(e-mail address removed)
http://www.geocities.com/opalpaweb/
 
B

Brandon McCombs

Arne said:
Case doesn't seam to matter, since it works when running from classes
(NetBeans/Eclipse runs directly from the "build" directory). But I'll make
sure I use the same case.


I've tried using both ProjectorButton, ProjectorControl, and the
ClassLoader.getSystemClassLoader().getResource()

and printed the resulting imgURL, and seen how this makes a different. It
all works as long as I dont run it from my JAR file.......


I thought so too. I'll follow your advise and create a small example and run
it through the test.

Thanks for trying to help me out. Your support has been invaluable :)

-Arne

Arne,

People don't seem to be listening to you about how you have already
tested your code in Eclipse and yet the same code does not work in the
jar file despite your files being in the jar file and in the right
location. A couple days ago in the comp.lang.java.gui newsgroup I
posted a message about this very same problem and so far they have not
been able to help me. I've tried all sorts of combinations of
class.getResource() and classLoader().getResource() and still can't get
icons to load when I use a jar file.

If I run my jar file right above the directory where my icons exist in
my file system then the icons load but that is only because the jar file
is referencing the version if the icons outside of the jar instead of
inside. One person mentioned that the icons need to be in the classpath
but never said how or where to set the classpath. I've tried to set a
classpath in my command window (Windows XP) and then run my jar but it
did not help. If you get the answer please post it so I can try it in
my environment.
 
O

opalpa

To be extra clear: say you have code like so:

package experiment;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import java.net.URL;
import java.io.*;
import javax.swing.*;
final class GetResourcePic {
private GetResourcePic() {}
public static void window(final String title, final Image body)
throws java.awt.AWTException
{
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame(title);
// JFrame.setDefaultLookAndFeelDecorated(true);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(new JLabel(new ImageIcon(body)));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}); // funky
}
public static void main(String a[]) throws AWTException, IOException
{
URL picurl =
GetResourcePic.class.getResource("GetResourcePic.gif");
System.out.println(""+picurl);
BufferedImage img = ImageIO.read(picurl);
window("GetResourcePic", img);
}
}

with manifest file:
Main-Class: experiment.GetResourcePic

Make/Get an image file, name it case sensitively,GetResourcePic.gif
(NOTE: case matters).

Compile into classes. Move image file to same directory that contains
GetResourcePic.class. See code run. Make jar. (check jar has all
classes and image file in correct directory, check case sensitivity)
See code run.

Change gif in source to giF (NOTE: capital at end). Compile into
classes. See code run. Make jar. See code fail.

Opalinski
(e-mail address removed)
http://www.geocities.com/opalpaweb/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top