Java Forum / General / February 2006
Where should I place resource-files like images ?
Arne Styve - 20 Feb 2006 11:12 GMT 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
Cyril - 20 Feb 2006 11:34 GMT 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
Thomas Weidenfeller - 20 Feb 2006 12:26 GMT > 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
 Signature The comp.lang.java.gui FAQ: ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq http://www.uni-giessen.de/faq/archiv/computer-lang.java.gui.faq/
Cyril - 20 Feb 2006 12:49 GMT 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
Thomas Weidenfeller - 20 Feb 2006 12:16 GMT > 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
 Signature The comp.lang.java.gui FAQ: ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq http://www.uni-giessen.de/faq/archiv/computer-lang.java.gui.faq/
Arne Styve - 20 Feb 2006 12:35 GMT 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
>> What is the best strategy for placing image-files so that they will >> always be found, both when running the application from within Eclipse, [quoted text clipped - 18 lines] > > /Thomas Thomas Weidenfeller - 20 Feb 2006 13:42 GMT > 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.
 Signature The comp.lang.java.gui FAQ: ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq http://www.uni-giessen.de/faq/archiv/computer-lang.java.gui.faq/
Arne Styve - 21 Feb 2006 11:08 GMT >> 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 [quoted text clipped - 7 lines] > > /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..
opalpa@gmail.com opalinski from opalpaweb - 21 Feb 2006 12:31 GMT > 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 opalpa@gmail.com http://www.geocities.com/opalpaweb/
Arne Styve - 21 Feb 2006 13:01 GMT <opalpa@gmail.com> wrote in message news:1140525098.780296.146240@z14g2000cwz.googlegroups.com...
>> Is there a way to print the path from where getResource() starts to >> search from ? [quoted text clipped - 16 lines] > opalpa@gmail.com > 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
opalpa@gmail.com opalinski from opalpaweb - 21 Feb 2006 13:44 GMT 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 opalpa@gmail.com http://www.geocities.com/opalpaweb/
opalpa@gmail.com opalinski from opalpaweb - 21 Feb 2006 13:48 GMT 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 opalpa@gmail.com http://www.geocities.com/opalpaweb/
Arne Styve - 21 Feb 2006 14:22 GMT <opalpa@gmail.com> wrote in message news:1140529699.002734.250980@f14g2000cwb.googlegroups.com...
>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. 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
opalpa@gmail.com opalinski from opalpaweb - 21 Feb 2006 14:58 GMT > 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 opalpa@gmail.com http://www.geocities.com/opalpaweb/
Arne Styve - 21 Feb 2006 15:37 GMT <opalpa@gmail.com> wrote in message news:1140533933.768316.82030@g44g2000cwa.googlegroups.com...
>> Yepp, when I do a "jar -ft" on my JAR-file, I find: > [quoted text clipped - 4 lines] > 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.
>> This works fine if I use .getResource("/discon.gif"); and use the >> ClassLoader instead of ProjectorControl.class.getSource(). [quoted text clipped - 3 lines] > 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
opalpa@gmail.com opalinski from opalpaweb - 21 Feb 2006 20:20 GMT > 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 opalpa@gmail.com http://www.geocities.com/opalpaweb/
Brandon McCombs - 22 Feb 2006 00:34 GMT > <opalpa@gmail.com> wrote in message > news:1140533933.768316.82030@g44g2000cwa.googlegroups.com... [quoted text clipped - 31 lines] > > -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.
opalpa@gmail.com opalinski from opalpaweb - 22 Feb 2006 02:02 GMT What about the case thing? When loading from jar file case matters. When loading in windows outside of jar file case does not matter.
Opalinski opalpa@gmail.com http://www.geocities.com/opalpaweb/
opalpa@gmail.com opalinski from opalpaweb - 22 Feb 2006 02:23 GMT 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 opalpa@gmail.com http://www.geocities.com/opalpaweb/
Brandon McCombs - 22 Feb 2006 02:59 GMT > What about the case thing? When loading from jar file case matters. > When loading in windows outside of jar file case does not matter. > > Opalinski > opalpa@gmail.com > http://www.geocities.com/opalpaweb/ I changed the case of my filenames in my code and it worked. When i created the files MS Paint made them have uppercase file extensions and that's also how eclipse was looking at them so I had to refresh the images/ folder in eclipse after I renamed the files to .gif from .GIF.
thanks Opalinski. I've been working on this for a couple weeks now off and on and no one could ever figure it out to help.
Arne Styve - 22 Feb 2006 09:51 GMT <opalpa@gmail.com> wrote in message news:1140573302.829486.51580@g44g2000cwa.googlegroups.com...
> What about the case thing? When loading from jar file case matters. > When loading in windows outside of jar file case does not matter. > > Opalinski > opalpa@gmail.com > http://www.geocities.com/opalpaweb/ THANK YOU!! You made my day!!
You were absolutely correct. Case DOES matter. The extra anoying part here (since working in a M$ environment) is that we use Microsoft SourceSafe to manage our sourcefiles, and of some reason SourceSafe keeps changing the case on directories and file extensions now and then.....
I renamed from .GIF to .gif, and it worked.....
Thanks!
-Arne
steve - 22 Feb 2006 22:29 GMT >> <opalpa@gmail.com> wrote in message >> news:1140533933.768316.82030@g44g2000cwa.googlegroups.com... [quoted text clipped - 52 lines] > did not help. If you get the answer please post it so I can try it in > my environment. yep that's what i find , when my programs don't work. it's every body else's fault for not listening.
but then I wake up from my dream.
The following code works ( i know because i use it every day)
YOU DO NOT NEED ANY CLASS PATH TO POINT TO YOUR IMAGES IN YOUR ENVIRONMENT, nor do they need to be on the "class path"
public class MyProvidesReports implements ProvidesReports {
some other code here........ Getpictures(JobParams); some other code............
private void Getpictures(HashMap ReportParams) { java.net.URL Source; java.net.URL Source1;
Source = MyProvidesReports.class.getResource("/Images/Image1.png"); // this is a fixed format for all java platforms do not use "file.separator // Source1 = MyProvidesReports.class.getResource("/Images/Chop.png"); // this is a fixed format for all java platforms do not use "file.separator
// ReportParams.put("MyChop", Source1); ReportParams.put("CompanyLogo", Source); }
} you just need to compile the pictures into a directory
"/Images/Image1.png"
BUT NOTE: THE CHARACTER CASE, not all platforms ignore the case , "Images" is NOT the same as "images"
ALSO NOTE Do not use "file.separator" or strings with paths in, because file separators are different on each platform.
use the URL class, and a standard separator and it will always work.
the above code is for getting pictures so that their references can be passed to reports or buttons or whatever.
those 3-5 lines , will save your life every time, on every platform i have yet tested it on ( windows95/98/se/2000/NT/linux/osx/solaris/yellowdog)
Roedy Green - 21 Feb 2006 17:06 GMT >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.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Java custom programming, consulting and coaching.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|