I wanted to create a pretty button in my GUI. There is a tutorial describing how to make all kinds of pretty buttons.
The thing is, they use ImageIcon.
So next step was looking up how image icons work and what they do. There is another tutorial on the same site titled "How to use icons".
It provides you with this code:
/** Returns an ImageIcon, or null if the path was invalid. */
protected ImageIcon createImageIcon(String path,
String description) {
java.net.URL imgURL = getClass().getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL, description);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
The line java.net.URL imgURL = getClass().getResource(path) is very confusing to me. Why won't they do directly return new ImageIcon(path, description)?
getResource() searches the entire path available to the ClassLoader responsible for loading that class, searching for that resource. Including things like searching inside JAR files on the classpath, etc.
http://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getResource-java.lang.String-
getClass().getResource(path)
locates the icon on the classpath and gives back the URL to use to load it. This is different from what you suggest to use. The constructor that takes only String loads the icon from the filesystem. It is done via getClass().getResource(path) so that you can package your icon and all resources your application needs within your distribution jar and still find and load it. Otherwise you'd have to rely on some path on the filesystem and make sure they exist where you expect them so that you can work with relative paths.
The getClass().getResource(path) loads the resource in relation to where the class file sits. This will work from an IDE as well as after the class has been packaged into a JAR file
Related
I am trying to load an image to use as an icon in my application. The appropriate method according to this tutorial is:
protected ImageIcon createImageIcon(String path, String description)
{
java.net.URL imgURL = getClass().getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL, description);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
So, I placed the location of the file, and passed it as a parameter to this function. This didn't work, i.e. imgURL was null. When I tried creating the ImageIcon by passing in the path explicitly:
ImageIcon icon = new ImageIcon(path,"My Icon Image");
It worked great! So the application can pick up the image from an explicitly defined path, but didn't pick up the image using getResources(). In both cases, the value of the path variable is the same. Why wouldn't it work? How are resources found by the class loader?
Thanks.
getClass().getResource(path) loads resources from the classpath, not from a filesystem path.
You can request a path in this format:
/package/path/to/the/resource.ext
Even the bytes for creating the classes in memory are found this way:
my.Class -> /my/Class.class
and getResource will give you a URL which can be used to retrieve an InputStream.
But... I'd recommend using directly getClass().getResourceAsStream(...) with the same argument, because it returns directly the InputStream and don't have to worry about creating a (probably complex) URL object that has to know how to create the InputStream.
In short: try using getResourceAsStream and some constructor of ImageIcon that uses an InputStream as an argument.
Classloaders
Be careful if your app has many classloaders. If you have a simple standalone application (no servers or complex things) you shouldn't worry. I don't think it's the case provided ImageIcon was capable of finding it.
Edit: classpath
getResource is—as mattb says—for loading resources from the classpath (from your .jar or classpath directory). If you are bundling an app it's nice to have altogether, so you could include the icon file inside the jar of your app and obtain it this way.
As a noobie I was confused by this until I realized that the so called "path" is the path relative to the MyClass.class file in the file system and not the MyClass.java file. My IDE copies the resources (like xx.jpg, xx.xml) to a directory local to the MyClass.class. For example, inside a pkg directory called "target/classes/pkg. The class-file location may be different for different IDE's and depending on how the build is structured for your application. You should first explore the file system and find the location of the MyClass.class file and the copied location of the associated resource you are seeking to extract. Then determine the path relative to the MyClass.class file and write that as a string value with "dots" and "slashes".
For example, here is how I make an app1.fxml file available to my javafx application where the relevant "MyClass.class" is implicitly "Main.class". The Main.java file is where this line of resource-calling code is contained. In my specific case the resources are copied to a location at the same level as the enclosing package folder. That is: /target/classes/pkg/Main.class and /target/classes/app1.fxml. So paraphrasing...the relative reference "../app1.fxml" is "start from Main.class, go up one directory level, now you can see the resource".
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("../app1.fxml"));
Note that in this relative-path string "../app1.fxml", the first two dots reference the directory enclosing Main.class and the single "." indicates a file extension to follow. After these details become second nature, you will forget why it was confusing.
getResource by example:
package szb.testGetResource;
public class TestGetResource {
private void testIt() {
System.out.println("test1: "+TestGetResource.class.getResource("test.css"));
System.out.println("test2: "+getClass().getResource("test.css"));
}
public static void main(String[] args) {
new TestGetResource().testIt();
}
}
output:
test1: file:/home/szb/projects/test/bin/szb/testGetResource/test.css
test2: file:/home/szb/projects/test/bin/szb/testGetResource/test.css
getResourceAsStream() look inside of your resource folder. So the fil shold be placed inside of the defined resource-folder
i.e if the file reside in /src/main/resources/properties --> then the path should be /properties/yourFilename.
getClass.getResourceAsStream(/properties/yourFilename)
I've been putting all of my images for my Java application in a package called "rtype" inside src where I also also have my Class that deals with these images. I wanted to sort the images and put them in a folder of their own. When I do this, The images will no longer load into the class, and I know it's because I changed the file path. I've done some research and tried a few different things. This is basically what I had originally:
String walkingDown = "WalkingDown.gif";
ImageIcon ii;
Image image;
ii = new ImageIcon(this.getClass().getResource(walkingDown));
image = ii.getImage();
and It worked just fine before I moved the location of the images outside the location of the class. Now it cant find the images. Here is what I tried and found online to try (The folders Name is Sprites):
//use getClassLoader() inbetween to find out where exactly the file is
ii = new ImageIcon(this.getClass().getClassLoader().getResource(standingDown));
and
//Changing the path
String walkingDown = "src\\Sprites\\WalkingDown.gif";
//also tried a variation of other paths with no luck
I am using the C drive, but don't want to use "C" in my extension, as I want it to be accessible no matter where I put the project. I am fairly stuck at this point and have done enough looking into it to realize that It was time to ask.
I have a separate "package" for images with that name (in the src folder)
Try something like this:
try {
ClassLoader cl = this.getClass().getClassLoader();
ImageIcon img = new ImageIcon(cl.getResource("images/WalkingDown.gif"));
}
catch(Exception imageOops) {
System.out.println("Could not load program icon.");
System.out.println(imageOops);
}
Your variable is named walkingDown, but you pass in standingDown to the getResource() method.
new ImageIcon("src/Sprites/WalkingDown.gif");
I have a Java project called MyProject. I have a few different packages (keeping names simple for the purpose of this question), as follows:
src/PackageA
src/PackageA/PackageAa
src/PackageA/PackageAa/PackageAaa
src/PackageB
src/PackageB/PackageBa
src/PackageB/PackageBa/PackageBaa
I have a class
src/PackageA/PackageAa/PackageAaa/MyJavaFile.java
And I have an image
src/PackageB/PackageBa/PackageBaa/MyImage.png
Inside of MyJavaFile.java, I would like to declare an Image oject of MyImage.png
Image img = new Image(....what goes here?...)
How can I do this?
You could either call Class.getResource and specify a path starting with /, or ClassLoader.getResource and not bother with the /:
URL resource = MyJavaFile.class
.getResource("/PackageB/PackageBa/PackageBaa/MyImage.png");
or:
URL resource = MyJavaFile.class.getClassLoader()
.getResource("PackageB/PackageBa/PackageBaa/MyImage.png");
Basically Class.getResource will allow you to specify a resource relative to the class, but I don't think it allows you to use ".." etc for directory navigation.
Of course, if you know of a class in the right package, you can just use:
URL resource = SomeClassInPackageBaa.class.getResource("MyImage.png");
(I'm assuming you can pass a URL to the Image constructor in question. There's also getResourceAsStream on both Class and ClassLoader.)
you can use relative path since the the relative path is project folder.
ImageIcon img = new ImageIcon("src/PackageB/PackageBa/PackageBaa/MyImage.png");
/folderB/folderBa/folderBaa/MyImage.png
The image can stored into a project folder location .eg: /images/MyImage.png
Then try:
Image img = new Image(/images/MyImage.png);
Using a file path is not possible when running a program that's in a jar file, especially if the program is being loaded as an applet or WebStart application then you can use ClassLoader to get image.
use the following code to load the images:
ClassLoader cldr = this.getClass().getClassLoader();
java.net.URL imageURL = cldr.getResource("/PackageB/PackageBa/PackageBaa/MyImage.png");
ImageIcon aceOfDiamonds = new ImageIcon(imageURL);
This IS the best way to handle all images and icons in a JAR App.
Once you've zipped up all of your images and icons into its own JAR file - Configure your build path by adding the images JAR file into your libraries tab so that its now included in your classpath.
Then simply use the following 3x lines of code at the start of your constuctor to access any image you need for anything including a SystemTray image which doesn't accept the simple ImageIcon's as its main icon (weird I know). The 3x lines are:
URL iconUrl = this.getClass().getResource("/image-iconb.png");
Toolkit tk = this.getToolkit();
imageIcon = tk.getImage(iconUrl);
(imageIcon is just a constructor declared Image variable)
Now you can set a window icon as simply as:
setIconImage(imageIcon );
and at the same time use the same variable when setting the System TrayIcon by declaring:
trayIcon = new TrayIcon(imageIcon, "SystemTray Demo", popupMenu);
The above allows you to declare Images or ImageIcons easily and centrally without running the risk of not keeping image resources in the right place. It keeps it nice and tidy, with the JAR containing all your images automatically compiled at run time and distribution of your program.
As a bonus, once the JAR is registered in your classpath - you can keep adding any other images into the same JAR at any time without any fuss too - Everything just works and the added images are instantly available to your app.
Much better in my view.
Use the getResource method to read resources inside the src root. For example, the following code retrieves images from a folder src/images.
// Get current classloader
ClassLoader cl = this.getClass().getClassLoader();
// Create icons
Icon saveIcon = new ImageIcon(cl.getResource("images/save.gif"));
Icon cutIcon = new ImageIcon(cl.getResource("images/cut.gif"));
The example assumes that the following entries exist in the application's JAR file:
images/save.gif
images/cut.gif
Image img = new Image("./src/PackageB/PackageBa/PackageBaa/MyImage.png");
This shall go the path of the image is first inside src (source) then package so the program would access the image this way.
I've seen many different examples showing how to set a JFrame's IconImage so that the application uses that icon instead of the standard coffee mug. None of them are working for me.
Here's "my" code (heavily borrowed from other posts and the internet at large):
public class MyApp extends JFrame
{
public MyApp()
{
ImageIcon myAppImage = loadIcon("myimage.jpg");
if(myAppImage != null)
setIconImage(myAppImage.getImage());
}
private ImageIcon loadIcon(String strPath)
{
URL imgURL = getResource(strPath);
if(imgURL != null)
return new ImageIcon(imgURL);
else
return null;
}
}
This code fails down in loadIcon when making a call to the getResource() method. To me, there's only 2 possibilities here: (1) the myImage.jpg is in the wrong directory, or (2) getResource() doesn't like something about my image (I had to convert it from CMYK to RGB in Photoshop so I could use the same image elsewhere with ImageIO.)
I have used the System.out.println(new File(".").getAbsolutePath()); trick to locate the directory where the image JPG should be stored, and still nothing worked. I have subsequently placed the JPG in just about every directory inside my project, just to rule file location out as the culprit.
So that leaves me to believe there's something that getResource() doesn't like about the JPG itself. But I have now already exhausted my understanding of images and icons in the mighty, wide world of Swing.
My JPG loads fine in other image viewers, so that's ruled out as well. Anyone have any ideas?
Thanks in advance!
I have tried following which was a answer for same kind of question like yours. And it works for me.
Try putting your images in a separate folder outside of your src
folder. Then, use ImageIO to load your images. (answered Aug 27 '13 at 0:18
AndyTechGuy)
frame.setIconImage(ImageIO.read(new File("res/icon.png")));
put the image in the root of the classpath and say getResource("classpath:myimage.jpg");
The problem with your code is that jvm is unsure where to lookup the image file so its returning null.
Here is a nice link about classpath
It should be
if(imgURL != null)
^
instead of
if(imgURL !- null)
and
URL imgURL = this.getClass().getResource(strPath);
instead of
URL imgURL = getResource(strPath);
Then it works fine, if "myimage.jpg" is in the same dir with MyApp.class
Two suggestions:
Try using the getClass().getResource("x.jpg"), and putting the file directly in the same folder as the .class file of the class you are in.
Make sure the name is identical in case - some operating systems are case sensitive, and within a JAR, everything is case sensitive.
You can try to use a "/" before your filename.
getClass().getResource("/myimage.jpg")
If you look into your build-output folder (target) you can look for your class where you are trying to get your resource from.
Your resources will probably be copied in some folders above.
For example your target directory could look like this:
target
|- de.example.app
|- Main.class
|- Main-x.y.z.jar
|- myimage.jpg
So if you just go for getClass().getResource("myimage.jpg") it will look under the folder target/de/example/app and won't find a jpg there.
You need to tell him that you want to look under the root-folder (target/**). That's why you need to place a "/" before your file.
I'm making a torpedo game for school in java with swing gui, please see the zipped source HERE.
I use custom button icons and mouse cursors of images stored in the /bin/resource/graphics/default folder's subfolders, where the root folder is the program's root folder (it will be the root in the final .jar as well I suppose) which apart from "bin" contains a "main" folder with all the classes. The relative path of the resources is stored in MapStruct.java's shipPath and mapPath variables.
Now Battlefield.java's PutPanel class finds them all right and sets up its buttons' icons fine, but every other class fail to get their icons, e.g. Table.java's setCursor, which should set the mouse cursor for all its elements for the selected ship's image or Field.java's this.button.setIcon(icon); in the constructor, which should set the icon for the buttons of the "water".
I watched with debug what happens, and the images stay null after loading, though the paths seem to be correct. I've also tried to write a test file in the image folder but the method returns a filenotfound exception. I've tried to get the path of the class to see if it runs from the supposed place and it seems it does, so I really can't find the problem now.
Could anyone please help me?
Thank you.
You need to load icons like this:
ClassLoader cl= this.getClass().getClassLoader();
URL imageURL = cl.getResource("resources/...");
ImageIcon icon = new ImageIcon(imageURL);
And you need to add your resource folder to the classpath in Eclipse. Note that the path is not a file path, this way it will work if you decide to bundle your app in a jar file.
btnRegistration.setIcon(createImageIcon("reg.png"));
protected ImageIcon createImageIcon(String path) {
java.net.URL imgURL = Master.class.getClassLoader().getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL);
} else {
System.out.println("Couldn't find file: " + path);
return null;
}
}
here btnRegistration is my JButton
Master is my Class
and reg.png is my image that is belong in my project