Loading resources like images while running project distributed as JAR archive - java

I am having a error for my GUI. Trying to set title bar icon then be included in a Runnable JAR.
BufferedImage image = null;
try {
image = ImageIO.read(getClass().getClassLoader().getResource("resources/icon.gif"));
}
catch (IOException e) {
e.printStackTrace();
}
frame.setIconImage(image);
Here is the error I am getting:
Exception in thread "main" java.lang.IllegalArgumentException: input == null!
at javax.imageio.ImageIO.read(Unknown Source)
at GUI.<init>(GUI.java:39)
at GUI.main(GUI.java:351)
The image is in the correct directory which "resources" folder is the root of the
project file

First of all, change this line :
image = ImageIO.read(getClass().getClassLoader().getResource("resources/icon.gif"));
to this :
image = ImageIO.read(getClass().getResource("/resources/icon.gif"));
More info, on as to where lies the difference between the two approaches, can be found on this thread - Different ways of loading a Resource
For Eclipse:
How to add Images to your Resource Folder in the Project
For NetBeans:
Handling Images in a Java GUI Application
How to add Images to the Project
For IntelliJ IDEA:
Right-Click the src Folder of the Project. Select New -> Package
Under New Package Dialog, type name of the package, say resources. Click OK
Right Click resources package. Select New -> Package
Under New Package Dialog, type name of the package, say images. Click OK
Now select the image that you want to add to the project, copy it. Right click resources.images package, inside the IDE, and select Paste
Use the last link to check how to access this file now in Java code. Though for this example, one would be using
getClass().getResource("/resources/images/myImage.imageExtension");
Press Shift + F10, to make and run the project. The resources and images folders, will be created automatically inside the out folder.
If you are doing it manually :
How to add Images to your Project
How to Use Icons
A Little extra clarification, as given in this answer's first
code example.
QUICK REFERENCE CODE EXAMPLE(though for more detail consider, A little extra clarification link):
package swingtest;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
/**
* Created with IntelliJ IDEA.
* User: Gagandeep Bali
* Date: 7/1/14
* Time: 9:44 AM
* To change this template use File | Settings | File Templates.
*/
public class ImageExample {
private MyPanel contentPane;
private void displayGUI() {
JFrame frame = new JFrame("Image Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
contentPane = new MyPanel();
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private class MyPanel extends JPanel {
private BufferedImage image;
public MyPanel() {
try {
image = ImageIO.read(MyPanel.class.getResource("/resources/images/planetbackground.jpg"));
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return image == null ? new Dimension(400, 300): new Dimension(image.getWidth(), image.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
}
public static void main(String[] args) {
Runnable runnable = new Runnable() {
#Override
public void run() {
new ImageExample().displayGUI();
}
};
EventQueue.invokeLater(runnable);
}
}

There's a much easier way to load and set an image as a frame icon:
frame.setIconImage(
new ImageIcon(getClass().getResource("/resources/icon.gif")).getImage());
And thats all :)! You don't even have to use a try-catch block because ImageIcon does not throw any declared exceptions. And due to getClass().getResource(), it works both from file system and from a jar depending how you run your application.
If you need to check whether the image is available, you can check if the URL returned by getResource() is null:
URL url = getClass().getResource("/resources/icon.gif");
if (url == null)
System.out.println( "Could not find image!" );
else
frame.setIconImage(new ImageIcon(url).getImage());

The image files must be in the directory resources/ in your JAR, as shown in How to Use Icons and this example for the directory named images/.

Related

Compiled jar file does not work because can not fin image file [duplicate]

I am having a error for my GUI. Trying to set title bar icon then be included in a Runnable JAR.
BufferedImage image = null;
try {
image = ImageIO.read(getClass().getClassLoader().getResource("resources/icon.gif"));
}
catch (IOException e) {
e.printStackTrace();
}
frame.setIconImage(image);
Here is the error I am getting:
Exception in thread "main" java.lang.IllegalArgumentException: input == null!
at javax.imageio.ImageIO.read(Unknown Source)
at GUI.<init>(GUI.java:39)
at GUI.main(GUI.java:351)
The image is in the correct directory which "resources" folder is the root of the
project file
First of all, change this line :
image = ImageIO.read(getClass().getClassLoader().getResource("resources/icon.gif"));
to this :
image = ImageIO.read(getClass().getResource("/resources/icon.gif"));
More info, on as to where lies the difference between the two approaches, can be found on this thread - Different ways of loading a Resource
For Eclipse:
How to add Images to your Resource Folder in the Project
For NetBeans:
Handling Images in a Java GUI Application
How to add Images to the Project
For IntelliJ IDEA:
Right-Click the src Folder of the Project. Select New -> Package
Under New Package Dialog, type name of the package, say resources. Click OK
Right Click resources package. Select New -> Package
Under New Package Dialog, type name of the package, say images. Click OK
Now select the image that you want to add to the project, copy it. Right click resources.images package, inside the IDE, and select Paste
Use the last link to check how to access this file now in Java code. Though for this example, one would be using
getClass().getResource("/resources/images/myImage.imageExtension");
Press Shift + F10, to make and run the project. The resources and images folders, will be created automatically inside the out folder.
If you are doing it manually :
How to add Images to your Project
How to Use Icons
A Little extra clarification, as given in this answer's first
code example.
QUICK REFERENCE CODE EXAMPLE(though for more detail consider, A little extra clarification link):
package swingtest;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
/**
* Created with IntelliJ IDEA.
* User: Gagandeep Bali
* Date: 7/1/14
* Time: 9:44 AM
* To change this template use File | Settings | File Templates.
*/
public class ImageExample {
private MyPanel contentPane;
private void displayGUI() {
JFrame frame = new JFrame("Image Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
contentPane = new MyPanel();
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private class MyPanel extends JPanel {
private BufferedImage image;
public MyPanel() {
try {
image = ImageIO.read(MyPanel.class.getResource("/resources/images/planetbackground.jpg"));
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return image == null ? new Dimension(400, 300): new Dimension(image.getWidth(), image.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
}
public static void main(String[] args) {
Runnable runnable = new Runnable() {
#Override
public void run() {
new ImageExample().displayGUI();
}
};
EventQueue.invokeLater(runnable);
}
}
There's a much easier way to load and set an image as a frame icon:
frame.setIconImage(
new ImageIcon(getClass().getResource("/resources/icon.gif")).getImage());
And thats all :)! You don't even have to use a try-catch block because ImageIcon does not throw any declared exceptions. And due to getClass().getResource(), it works both from file system and from a jar depending how you run your application.
If you need to check whether the image is available, you can check if the URL returned by getResource() is null:
URL url = getClass().getResource("/resources/icon.gif");
if (url == null)
System.out.println( "Could not find image!" );
else
frame.setIconImage(new ImageIcon(url).getImage());
The image files must be in the directory resources/ in your JAR, as shown in How to Use Icons and this example for the directory named images/.

How to add an ImageIcon to a JToolBar

I am trying to add a icon to a toolbar but what is the best place to put it in? My desktop or should I make a new file in the project file or add all the pictures in because it is not showing and this is my code:
JToolBar toolBar = new JToolBar();
String[] iconFiles = {"pen-icon","",""};
String[] buttonLabels = {"New","Open","Save"};
icon = new ImageIcon[iconFiles.length];
Obutton = new JButton[buttonLabels.length];
for (int i = 0; i < buttonLabels.length; ++i) {
icon[i] = new ImageIcon(iconFiles[i]);
Obutton[i] = new JButton(icon[i]);
Obutton[i].setToolTipText(buttonLabels[i]);
if (i == 3)
toolBar.addSeparator();
toolBar.add(Obutton[i]);
}
I would use an Action. Here is the AbstractAction constructor
public AbstractAction(String name, Icon icon) - Creates an Action with the specified name and small icon.
Parameters:
name - the name (Action.NAME) for the action; a value of null is ignored
icon - the small icon (Action.SMALL_ICON) for the action; a value of null is ignored
The benefit of using an Action is that is can be reused for components with similar purposes. So say you want to have an icon button in the toolbar to open a file, and also have a JMenuItem in a JMenu that also opens a file. They could share the same action, thus sharing the same icon, action command, and action to perform.
Action action = new AbstractAction("someActionCommand", someIcon) {
#Override
public void actionPerformed(ActionEvent e) {
// do something.
}
};
toolbar.add(action);
The above will automatically put the icon for you, but not the String. In a JMenuItem it would put both the String and the icon.
Then just add the Action to the tool bar.
See more at How to use Actions
To answer you real question, as #MadProgrammer noted, you should be loading your images as an embedded resource, using
ImageIcon icon = new ImageIcon(MyClass.class.getResource("/resources/images/image.png"));
where the /resources/images directory is in the src, and getResource() returns a URL. Upon build, your IDE should copy the files into the class path for you.
ProjectRoot
src
resources
images
image.png
You'll come to find that when using a file from the file system, will not work upon time of deployment
Here's an example, where the JMenuItem and the JToolBar button share the same action. Notice that in the JToolBar all I have to do is add the Action, I don't need to create a button for it. The JToolBar automatically makes it a button, without the action command
I use this "open.gif" from the below file structure and use
ImageIcon icon = new ImageIcon(
ActionTest.class.getResource("/resources/image/open.gif"));
Here's the result
Here's the code. Enjoy!
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;
public class ActionTest {
public ActionTest() {
ImageIcon openIcon = new ImageIcon(
ActionTest.class.getResource("/resources/image/open.gif"));
ImageIcon saveIcon = new ImageIcon(
ActionTest.class.getResource("/resources/image/save.gif"));
ImageIcon newIcon = new ImageIcon(
ActionTest.class.getResource("/resources/image/new.gif"));
Action openAction = new AbstractAction("Open", openIcon) {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Open File");
}
};
Action saveAction = new AbstractAction("Save", saveIcon) {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Save File");
}
};
Action newAction = new AbstractAction("New", newIcon) {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("New File");
}
};
JMenuItem openMenuItem = new JMenuItem(openAction);
JMenuItem saveMenuItem = new JMenuItem(saveAction);
JMenuItem newMenuItem = new JMenuItem(newAction);
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
fileMenu.add(openMenuItem);
fileMenu.add(saveMenuItem);
fileMenu.add(newMenuItem);
menuBar.add(fileMenu);
JToolBar toolBar = new JToolBar();
toolBar.add(Box.createHorizontalGlue());
toolBar.setBorder(new LineBorder(Color.LIGHT_GRAY, 1));
toolBar.add(newAction);
toolBar.add(openAction);
toolBar.add(saveAction);
JFrame frame = new JFrame("Toolbar and Menu Test");
frame.setJMenuBar(menuBar);
frame.add(toolBar, BorderLayout.PAGE_START);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ActionTest();
}
});
}
}
Resources of this type are typically best contained within the application context (such as a jar file). This reduces the chances of someone tampering with it as it's much more time consuming to unpack, modify and repack a jar file then simply replace a file. It also reduces what you need to distribute as it becomes self-contained.
These are known as embedded resources.
Where you would put them within this context is up to up, many people use a "resources" folder to store these types of files, but sometimes, you may want something that is relative to the context of the class. It's up to you.
This raises issues with loading these resources, as you can no longer reference them using something like File.
In general you can use Class#getResource(String), which returns a URL or Class#getResourceAsStream(String) which returns a InputStream. This provides you with all you need to load these embedded resources.
ImageIcon(String) expects the value to be a file reference, which means it won't work for embedded resources, but ImageIcon provides a constructor that takes a URL as a reference, this means you would need to use
icon[i] = new ImageIcon(getClass().getResource(iconFiles[i]));
To load your images.
Based on your example, the images would need to be relative to the class (ie within a directory structure the same as your package structure). How you achieve this will depend on your development environment.
Remember, you can also specify relative paths to getResource and even an absolute path in some contexts. An absolute path basic prefixes the elements of class path to the specified path when it searches for the resources.

Why does this simple code not work

I am having trouble with this simple example code from the book. It is supposed to represent the same image 2 times in one window (north and south labels), one above the other. When I run it, it displays this instead of this (I am sorry for not cutting the images or resizing them) Below is my code. I am running Eclipse Juno on Ubuntu 13.04.
package gui;
import java.awt.BorderLayout;
import javax.swing.*;
public class Gui {
public static void main(String[] args) {
JLabel northLabel = new JLabel ( "North" );
ImageIcon labelIcon = new ImageIcon ("GUItip.gif");
JLabel centerLabel = new JLabel (labelIcon);
JLabel southLabel = new JLabel (labelIcon);
southLabel.setText("South");
JFrame application = new JFrame();
application.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
application.add(northLabel, BorderLayout.NORTH);
application.add(centerLabel, BorderLayout.CENTER);
application.add(southLabel, BorderLayout.SOUTH);
application.setSize(300, 300);
application.setVisible(true);
}
}
You need to concentrate on the following statement:
ImageIcon labelIcon = new ImageIcon ("GUItip.gif");
When initiating new ImageIcon.. it searches the provided address in execution folder by default i.e. in this case "GUItip.gif" shall be searched within workspace/user directory.
One solution is to make available GUItip.gif image in you workspace (program execution) folder.
Another solution would be to provide absolute path.. eg.
C:\USER\Workspace\project_name\GUItip.gif
Though a better approach would be to create a specific folder where you save all images used in your project. Create a final static String variable with absolute path to your folder. Now it would be easy for any programmer in that project to know where to look for images.
There are good approaches to use this mapping.. through XML to be loaded in the beginning.. through resourcebundle etc but that is a different topic altogether.
The image probably isn't loading properly. Try using a try/catch block to see if that's the case.
Ex:
Image img;
File f = new File(//image url);
try {
img = ImageIO.read(f);
} catch (IOException e) {
String curr_dir = System.getProperty("user.dir");
throw new IllegalArgumentException("Image could not be found from " + curr_dir);
}
ImageIcon labelIcon = new ImageIcon(img);

Image won't display in JLabel

I've gone through every post I could find on this site and the Java tutorials and I still can't figure out why my code isn't working. Even when I copy/paste other peoples' code, it still doesn't work.
I've made a dummy program just to test this out and the code looks like so:
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import javax.swing.ImageIcon;
public class gui extends JFrame {
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
gui frame = new gui();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public gui() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 900, 700);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JLabel lblNewLabel = new JLabel(new ImageIcon("bg.png"));
contentPane.add(lblNewLabel);
}
}
The background image I'm trying to display, bg.png, is located in the project's root folder. I tried multiple formats for the path string with no success. What am I doing wrong?
What you're doing wrong is that when you call new ImageIcon("bg.png"), you try loading the bg.png file from the current directory. The current directory is the directory from which java is executed. And the current directory is probably not the directory you believe when you execute java from your IDE.
Use the following code to display the current directory:
File dir1 = new File (".");
System.out.println("current directory: " + dir1.getAbsolutePath());
You should probably load the png file from the classpath, using Class.getResource("/images/bg.png"). Create an images folder in your source directory, and put the file in this directory. Your IDE will copy it to the target folder, along with the .class files. If you're not using an IDE, then you'll have to copy it yourself.
EDIT:
After more investigations, it appeared that the root cause of the problem was the use of the null layout. The above still stands, though, because loading a file from the current directory is not a good idea.
You're looking for the image as a file. When you do that the searches are all done in a path relative to the user directory which you can get via
// code not tested
System.out.println(System.getProperty("user.dir"));
So you will likely have to adjust your image's path to get it as a file. The other option is to get it as a resource as noted by Siva Charan in which case the path is relative to the location of your class files.
Oh and once you study and use the layout managers, they become intuitive, and creating and especially maintaing your GUI's become much easier.
Try this way:-
ImageIcon icon = createImageIcon("bg.png", "image description");
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;
}
}
Just simply put your bg.png, alongside your gui.class file. That will do, if you write this code
private ImageIcon getImage(String path)
{
URL url = getClass().getResource(path);
System.out.println(url);
if (url != null)
return (new ImageIcon(url));
return null;
}
More information can be found on Access to Resources
Here path = "bg.png"; or if it's inside some folder than path = "someFolder/bg.png";
So you be writing something like this :
JLabel lblNewLabel = new JLabel(getImage("bg.png"));
lblNewLabel.setBounds(30, 30, 100, 100);
Hope that might help.
Regards
You might need to debug it and check if the image file is loaded correctly. And then you need to check if the JLabel Component gets its size because adding the image to the JLabel wouldn't expand the JLabel.
First you should try to see the image handler has its width and height.

Using an ImageIcon and a JLabel

My goal is to have an imageIcon and add it so a JLabel so it will appear on my GUI. So far my code is:
package classes;
import javax.swing.*;
public class Picture extends JFrame {
private ImageIcon _image1;
private JLabel _mainLabel;
public Picture(){
_image1 = new ImageIcon("picture1.jpg");
_mainLabel = new JLabel(_image1);
add(_mainLabel);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
package classes;
public class Driver {
public static void main(String[] args) {
Picture p = new Picture();
}
}
The problem is the picture does not appear on my GUI. If anyone has any suggestions please let me know thanks!
Are you sure that Java is looking in the right location for your picture1.jpg file? Is this file located in the current working directory?
Put this code somewhere in your program so that it gets called when the program is run:
// show the current working directory
System.out.println("current working directory is: " + System.getProperty("user.dir"));
The String returned will tell you where Java is looking, where your current working directory is located. You can then use that information to adjust your path or you could always just use the full path to the image file.
Edit:
Also, don't forget to pack your JFrame so that it will layout the components and size itself accordingly:
public Picture() {
_image1 = new ImageIcon(IMAGE);
_mainLabel = new JLabel(_image1);
add(_mainLabel);
pack(); // to tell the layout managers to set up the GUI
setLocationRelativeTo(null); // center things
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
For setting image to jlabel simple put one line code in your program :
yourlabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("your image location here")));
we can set Jlabel with image and text also.

Categories