Where should I place resource-files like images ?

Discussion in 'Java' started by Arne Styve, Feb 20, 2006.

  1. Arne Styve

    Arne Styve Guest

    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
    Arne Styve, Feb 20, 2006
    #1
    1. Advertising

  2. Arne Styve

    Cyril Guest

    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
    Cyril, Feb 20, 2006
    #2
    1. Advertising

  3. Arne Styve wrote:
    > 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
    --
    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/
    Thomas Weidenfeller, Feb 20, 2006
    #3
  4. Cyril wrote:
    > 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
    --
    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/
    Thomas Weidenfeller, Feb 20, 2006
    #4
  5. Arne Styve

    Arne Styve Guest

    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

    "Thomas Weidenfeller" <> wrote in message
    news:dtcbvk$6in$...
    > Arne Styve wrote:
    >> 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
    > --
    > 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, Feb 20, 2006
    #5
  6. Arne Styve

    Cyril Guest

    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
    Cyril, Feb 20, 2006
    #6
  7. Arne Styve wrote:
    > 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.
    --
    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/
    Thomas Weidenfeller, Feb 20, 2006
    #7
  8. Arne Styve

    Arne Styve Guest

    "Thomas Weidenfeller" <> wrote in message
    news:dtcbvk$6in$...
    > Arne Styve wrote:
    >> 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
    > --
    > 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/


    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..
    Arne Styve, Feb 21, 2006
    #8
  9. > 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

    http://www.geocities.com/opalpaweb/
    opalinski from opalpaweb, Feb 21, 2006
    #9
  10. Arne Styve

    Arne Styve Guest

    <> wrote in message
    news:...
    >> 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
    >
    > 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
    Arne Styve, Feb 21, 2006
    #10
  11. 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

    http://www.geocities.com/opalpaweb/
    opalinski from opalpaweb, Feb 21, 2006
    #11
  12. 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

    http://www.geocities.com/opalpaweb/
    opalinski from opalpaweb, Feb 21, 2006
    #12
  13. Arne Styve

    Arne Styve Guest

    <> wrote in message
    news:...
    >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
    Arne Styve, Feb 21, 2006
    #13
  14. > 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

    http://www.geocities.com/opalpaweb/
    opalinski from opalpaweb, Feb 21, 2006
    #14
  15. Arne Styve

    Arne Styve Guest

    <> wrote in message
    news:...
    >> 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.
    >


    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().

    >
    > 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
    Arne Styve, Feb 21, 2006
    #15
  16. Arne Styve

    Roedy Green Guest

    On Mon, 20 Feb 2006 12:12:52 +0100, "Arne Styve" <>
    wrote, quoted or indirectly quoted someone who said :

    >
    >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.
    --
    Canadian Mind Products, Roedy Green.
    http://mindprod.com Java custom programming, consulting and coaching.
    Roedy Green, Feb 21, 2006
    #16
  17. > 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

    http://www.geocities.com/opalpaweb/
    opalinski from opalpaweb, Feb 21, 2006
    #17
  18. Arne Styve wrote:
    > <> wrote in message
    > news:...
    >>> 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.
    >>

    >
    > 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().

    >> 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
    >
    >


    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.
    Brandon McCombs, Feb 22, 2006
    #18
  19. 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

    http://www.geocities.com/opalpaweb/
    opalinski from opalpaweb, Feb 22, 2006
    #19
  20. 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

    http://www.geocities.com/opalpaweb/
    opalinski from opalpaweb, Feb 22, 2006
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Gene
    Replies:
    0
    Views:
    571
  2. Nathan Sokalski
    Replies:
    2
    Views:
    517
    Nathan Sokalski
    Sep 14, 2008
  3. ~~~ .NET Ed ~~~

    How should control images should be handled?

    ~~~ .NET Ed ~~~, Oct 31, 2004, in forum: ASP .Net Building Controls
    Replies:
    1
    Views:
    221
    John Saunders
    Nov 3, 2004
  4. Nathan Sokalski

    Resource Files, Images, And The ImageUrl Property

    Nathan Sokalski, Sep 14, 2008, in forum: ASP .Net Building Controls
    Replies:
    3
    Views:
    1,222
    Allen Chen [MSFT]
    Sep 16, 2008
  5. vj
    Replies:
    3
    Views:
    230
Loading...

Share This Page