I have problem with Image Icons. I know that this have been asked before, but I can't figure out how to fix this, becouse I think my problem is different. When I launch app with eclipse, all works. But when I make it runnable jar, it won't show images.
Some code of my ImagesHolder Class :
package Clicker;
import javax.swing.ImageIcon;
public class ImagesHolder {
final public ImageIcon AccessoriesIcon = new ImageIcon("Images/Part_Accessories.png");
final public ImageIcon BodyIcon = new ImageIcon("Images/Part_Body.png");
final public ImageIcon BrakesIcon = new ImageIcon("Images/Part_Brakes.png");
final public ImageIcon CoolingIcon = new ImageIcon("Images/Part_Cooling.png");
final public ImageIcon ElectronicsIcon = new ImageIcon("Images/Part_Electronics.png");
final public ImageIcon EngineIcon = new ImageIcon("Images/Part_Engine.png");
final public ImageIcon ExaustIcon = new ImageIcon("Images/Part_Exaust.png");
final public ImageIcon FuelIcon = new ImageIcon("Images/Part_Fuel.png");
final public ImageIcon InteriorIcon = new ImageIcon("Images/Part_Interior.png");
final public ImageIcon SteeringIcon = new ImageIcon("Images/Part_Steering.png");
final public ImageIcon SuspensionIcon = new ImageIcon("Images/Part_Suspension.png");
final public ImageIcon TransmissionIcon = new ImageIcon("Images/Part_Transmission.png");
final public ImageIcon TiresIcon = new ImageIcon("Images/Part_Tires.png");
And If I make Images as URL, i can't reset image icons, like here (I have Labels and I want to change label icon)
Labels example :
public JLabel AccessoriesLVL1Label = new JLabel(ImagesHolder.LockedIcon);
AccessoriesLVL1Label.setHorizontalTextPosition(JLabel.CENTER);
AccessoriesLVL1Label.setVerticalTextPosition(JLabel.BOTTOM);
AccessoriesLVL1Label.setText("<html>Accessories LVL 1<br>" + "Count: " + Part.parts[1]);
And change :
if(CarMain.main[5] >=1){
jbtnSellAccessoriesLv1.setEnabled(true);
Labels.AccessoriesLVL1Label.setIcon(ImagesHolder.AccessoriesIcon);
}
Edited:
If I this :
final public ImageIcon MoneyIcon = new ImageIcon("Images/Money.png");
Make as :
URL MoneyIcon = ImagesHolder.class.getResource("/Money.png");
I get error in this line:
Labels.MoneyLabel.setIcon(ImagesHolder.MoneyIcon);
Error :
The method setIcon(Icon) in the type JLabel is not applicable for the arguments (URL)
There is an alternative for getting images from jar file:
Ideal way would be to have a resource directory under your project root and include it into the list of source code directories. This will result in all images there being copied into the JAR. If you make a sub directory there, resources/image, then you'll end up with a JAR that has an image directory. You access those images through the classloader:
classloader.getResourceAsStream("/image/image1.jpg");
or,
classloader.getResource("/image/image2.jpg");
Refer this link for in detail example.
Well, to sum up the previously given answers:
I guess a potential solution would be to use classloader as Dark Knight proposed. Furthermore you just need to create a new ImageIcon before setting it.
URL MoneyIcon = ImagesHolder.class.getResource("/Money.png");
Labels.MoneyLabel.setIcon(new ImagesIcon(ImagesHolder.MoneyIcon));
Because if you look through your code again, I guess it somewhat makes sense it does not work. I mean you want to set an ImageIcon, yet the last thing you have is an URL object. That this must throw an error should make sense. Yet as Andrew Thompson already said: You can construct an ImageIcon from that URL as displayed/explained above.
And since you also explained that you had issues with the directories (getting the structure from source to compiled) I want to add some links for further reading: If you just use 'plain' Java (no build tools) maybe this link can help: Copying data files upon build in Java/Eclipse. It is mainly written for Eclipse, but I guess most other IDEs should provide similar options.
From my current projects I could also recommend to use a tool like Maven. For smaller projects it might be a little over the top, but it takes of a lot of work (e.g. library handling, handling of resources like images etc.). These are just some parts that might be useful for you. If this is of interest for you I guess you will find lots of useful resources on the web since Maven (or other tools like Ant and Gradle) are quite commonly used.
Related
Yesterday my JavaFX-maven project was working fine in InteliJ IDE, but packed JRE with maven javaFX:jlink command was throwing similar exeption to this one I`ve got today with javaFX:run command:
Caused by: java.lang.IllegalArgumentException: Invalid URL: Invalid URL or resource not found
at javafx.graphics/javafx.scene.image.Image.validateUrl(Image.java:1125)
at javafx.graphics/javafx.scene.image.Image.<init>(Image.java:618)
at javafx.graphics/javafx.scene.image.ImageView.<init>(ImageView.java:194)
at org.example/org.example.GameMenu.construct(GameMenu.java:20)
at org.example/org.example.App.start(App.java:23)
The code that throws exeption:
public class GameMenu {
static int picOfChoice = (int) (Math.random() * 6);
public static Font font = Font.loadFont(Objects.requireNonNull(GameMenu.class.getResource("/utility/pixRectv2.ttf")).toExternalForm(), 48);
public static Font font2 = Font.loadFont(Objects.requireNonNull(GameMenu.class.getResource("/utility/pixRectv2.ttf")).toExternalForm(), 32);
public static Group menu = new Group();
public static Group construct() {
menu = new Group();
ImageView logo = new ImageView("menu/logo3.png");
Image backg3 = new Image("backg/backgPL" + picOfChoice + ".png", winWidth, winHeight, false, false);
ImageView backgV3 = new ImageView(backg3);
menu.getChildren().add(backgV3);
logo.setX(0);
logo.setY(0);
menu.getChildren().add(logo);//Logo is on top
return menu;
}}
No code on that line was changed. Resources folder was not moved. pom.xml wasnt changed. Those png`s are accesible for R/W and
even recognized by IDE as images
I have tried different path formatting (absolute path included) and it did not help. But ImageView logo = new ImageView("file:menu/logo3.png"); loads no image, while not throwing any exeption.
I have tried opening my other javaFX projects and they all work, while using similar project structure and similar way of useing new ImageView(). I have created new project with javaFX and it loads images just fine, so I wasnt able to recreate this problem.
I have opened this project on other machines, it throws same exeptions.
Fonts of javaFX in code above still load fine. Similar way of loading images ( through GameMenu.class.getResource ) works too.
The question: How to fix it and how to avoid it in future?
My project folder tree
UPD:
Thanks to #James_D and #Dmitriy Popov for answers;
I have added new method for path extraction via widely used .class.getResource()
So fixed code looks like
ImageView logo = new ImageView(Utility.getImageRes("/menu/logo3.png"));
Where Utility.getImageRes(String) is
public static String getImageRes(String path) {
return Objects.requireNonNull(Utility.class.getResource(path)).toExternalForm();
}
It works now, both with javaFX:run and jlink commands. Reason why previous method stopped working is still unknown.
I have created a GUI with Java Swing and wanting to create a custom toolbar according to my modules. Below are the images am wanting to use:
These images are placed in the same level as the src folder within my application. I am aware that I can perhaps create a jar with these images so that I can easily access them from within my application but do not know how. I have spent hours trying to make this work.
Below is my GUI that I have created ad wanting to beautify with these images for the toolbar else create an array of labels that will act as a navigation but either approach I couldn't get it to work.
The code below was my last attempt on this:
JToolBar toolbar1 = new JToolBar();
ImageIcon client = new ImageIcon("clients.png");
ImageIcon timesheet = new ImageIcon("timesheets.png");
JButton clientTB = new JButton(client);
JButton timesheetTB = new JButton(timesheet);
toolbar1.add(clientTB );
toolbar1.add(timesheetTB);
add(toolbar1, BorderLayout.NORTH);
I even moved these images and placed them within the class that's calling them.
What could I be doing wrong, please help?
You have a look at the JavaDocs for ImageIcon(String), the String value is "a String specifying a filename or path"
This is a problem, because your images aren't actually files, any more, they have been embedded within your application (typically within the resulting jar file) and no longer be treated like "normal files".
Instead, you need to use Class#getResource which searches the application's classpath for the named resource, something like...
// This assumes that the images are in the default package
// (or the root of the src directory)
ImageIcon client = new ImageIcon(getClass().getResource("/clients.png"));
Now, I have a personal dislike for ImageIcon, because it won't tell you when the image is loaded for some reason, like it can't be found or it's the wrong format.
Instead, I'd use ImageIO to read the image
ImageIcon client = new ImageIcon(ImageIO.read(getClass().getResource("/clients.png")));
which will do two things, first, it will throw a IOException if the image can't be loaded for some reason and two, it won't return until the image is fully loaded, which is helpful.
See Reading/Loading an Image for more details
I recently finished the basics of a game that I'm making and I was going to send it to some friends, but whenever they open the .jar it's just a grey window. When I heard that I assumed it was because of the way I got the images (I used a full path: C:\Users\etc). I did some Googling and found a way to get images that seemed more efficient.
private static Image[] mobImages = new Image[1];
public static void loadImages()
{
mobImages[1] = Handler.loadImage("res/EnemyLv1.png");
}
public static Image getMobImages(int index)
{
return mobImages[index];
}
That's what I would like to use. But I did that and changed the rest of my code to support that. And whenever I run a game I get a few errors. Which all point back to
this:
if(getBounds().intersects(tempEnemy.getBounds()))
and so probably the way I'm getting the images too. How could I fix this? And are there better ways to get Images? I've tried a few but they haven't worked.
EDIT: I finally solved all of the errors! :D The only problem is that none of the images appear. Here's my code again. Any more help? That would be fantastic! Thanks everybody for the support so far!
Hard to say whats going wrong in your code. However I recommend you put your image files into a package in the java project (so they will be part of the JAR file) and access them using Class.getResource()/Class.getResourceAsStream(). That avoids multiple pitfalls and keeps everything together.
A sample how to structure your images into the packages:
myproject
images
ImageLocator.class
MyImage1.jpg
MyImage2.jpg
The ImageLocator class then needs to use relative pathes (just the image name + extension) to access to resources.
public class ImageLocator {
public final static String IMAGE_NAME1 = "MyImage1.jpg";
public static Image getImage(final String name) {
URL url = ImageLocator.class.getResource(name);
Image image = Toolkit.getDefaultToolkit().createImage(url);
// ensure the image is loaded
return new ImageIcon(image).getImage();
}
}
This can be done more elegant, but this should get you started. Defining the image names as constants in the ImageLocator class avoids spreading the concrete path throughout the project (as long as the name is correct in ImageLocator, everything else will be checked by the compiler)
Your code still uses "C:\Users\Kids\Desktop\Java Game\Cosmic Defense\res\EnemyLv2.png" in Enemy.java. Are you sure this exists? If you moved the Cosmic Defense folder, it will not.
(You were talking about changing absolute paths to relative paths, so this may be your problem)
Part of the reason could be that your code is pointing to an index of "1" in an array of size 1, meaning that the only available index is in fact "0".
Try mobImages[0] = Handler.loadImage("res/EnemyLv1.png");
I'm trying to make my panel show image as background. I already can do that in NetBeans, but when I build my jar and run it image doesn't show there. I know I have to access it differently. I have seen many tutorials but every one of them shows how to do it with ImageIcon, but I don't need that, I need just Image. Can anyone point out what piece of code do I need to do this? Thanks.
This is my code for backgrounded JPanel:
public class JPanelWB extends JPanel { // Creates JPanel with given image as background.
private Image backgroundImage;
public JPanelWB(String fileName){
try {
backgroundImage = ImageIO.read(new File(fileName));
} catch (IOException ex) {
new JDialog().add(new Label("Could not open image."+ex.getMessage()));
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Draw the background image.
g.drawImage(backgroundImage, 0, 0, getWidth(),getHeight(),this);
}
}
Yeah, you're trying to read in the image as a file -- don't do that since files don't exist within a Jar file. Instead read it in as a resource.
Something like so:
public JPanelWB(String resourceName){
try {
// backgroundImage = ImageIO.read(new File(resourceName));
backgroundImage = ImageIO.read(getClass().getResource(resourceName));
} catch (IOException ex) {
new JDialog().add(new Label("Could not open image."+ex.getMessage()));
}
}
But note that resource path is different from file path. The resource path is relative to the location of your class files.
If you want to read new image and import it as background, people smarter than me already answered your question.
But, if your problem is similar to mine, then this migh help:
If you already have images to show, then the point is to call them from absolute path. Executable class form JAR will read drive created inside virtual machine, not the physical drive in your computer.
Put images in short-pathed folder like
C:\J\proj\img\
and call them with absolute path like
"C:\\J\\proj\\img\\your_image.png" // (Don't forget the double backslashes.)
(If you don't mind path lenght, leave them in image folder inside your project package, and call them from there.)
NetBeans will pack them into JAR with absolute path. On execution JRE will create JVM with that path in it, take the images from JAR and put them to that virtual path. Class will be able to find them, because it doesn't read path from physical drive, but from own virtual one newly created inside JVM.
In that case avoiding ImageIcon is just more clutter, not less.
You can add "blackBoard" as JLabel to be background to your JFrame, set its layout to null, something like this:
private JLabel blackBoard;
private JLabel noteToSelf;
//.....
blackBoard = new JLabel();
noteToSelf = new JLabel();
//.....
// putting JLabel "blackBoard" as background into JFrame
blackBoard.setIcon(new ImageIcon("c:\\Java\\images\\MarbleTable.png"));
getContentPane().add(blackBoard);
blackBoard.setBounds(1, 1, 400, 440);
blackBoard.setLayout(null);
and then add components into "blackBoard" instead of your JFrame, like this.
// putting JLabel "noteToSelf" onto background
noteToSelf.setIcon(new ImageIcon("c:\\Java\\images\\Sticker_a1.png"));
// or: noteToSelf.setText("Remind me at 6:30am...");
blackBoard.add(noteToSelf);
noteToSelf.setBounds(noteX, noteY, 64, 48);
Now your JFrame is table board and "blackBoard" is table sheet on it.
Hope this helps.
I wrote a method in order to get icon for my swing:
public Icon getIcon(String iconName) {
Icon icon = null;
if(iconName.equals("NEXT")){
icon = new ImageIcon( getClass().getResource("resources/img/next.png" ) );
}
return icon;
}
but
icon = new ImageIcon( getClass().getResource("resources/img/next.png" ) );
goes in null pointer
I created a source folder "resources" and a folder "img" inside it with "next.png" icon
Where's the problem?
Thanks
For this to work, the resources folder should be in the same folder as the folder corresponding to the package of this.getClass(). To start from the root of the classpath, use getClass().getResource("/resources/img/next.png"). (with a leading /)
so, I found the right method:
public static ImageIcon getImageIcon(String iconName) {
ImageIcon imageIcon = null;
if(iconName.equals("DOWNLOAD")){
imageIcon = new ImageIcon(ImagesLocation.class.getResource("/img/download.png"));
}
return imageIcon;
}
with a "resources" source folder at the same level of the project and with an img folder inside (package styled)
ImagesLocation is a generic class containing this method
For those in need of help that have come across this page in Google - I wrote an answer in another StackOverflow question giving the best way to handle images in JAVA apps so that you can easily access the images for all image method types in Java:
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();
someimgicon = tk.getImage(iconUrl);
(someimgicon is just a constructor declared Image variable)
Now you can set a window icon as simply as:
setIconImage(someimgicon);
and at the same time use the same variable when setting the System TrayIcon by declaring:
trayIcon = new TrayIcon(someimgicon, "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.