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.
Related
I'm new at Java and also swing. I just created a small app using JFrame and added some buttons and textFields, also I have a method which set the icon that I want for the taskbar and the one in the left corner.
When I run the program in Netbeans everything seems correctly, but when I build the project the icon it's not showing up. I tried a lot of things but none of them worked for me.
here's the method that I use for the program:
private void setIcon() {
ImageIcon imageIcon = new ImageIcon("src/main/java/icons/steam.png");
this.setIconImage(imageIcon.getImage());
}
And I call the method from the constructor.
Thank you.
EDIT 1:
Implementing what Andrew said, now I have this:
BufferedImage img = null;
try {
URL url = getClass().getResource("src/main/java/icons/steam.png");
img = ImageIO.read(url);
} catch (IOException e) {
}
this.setIconImage(img);
And that's on the constructor. But when I run it I get:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: input == null!
at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1400)
I tried different paths but I can't get it. And yes, I'm sure that "steam.png" is there.
I been looking for a solution to this and I finally get it (thanks to Andrew trough the comments)
First I edited my code as you can see in EDIT 1
After that, I got an IllegalArgumentException and the problem was that I didn't have a "resources" folder under /src
So I created my resources folder under src/main/resources and put my image inside
Then I got it using
URL url = getClass().getResource("/icons/steam.png");
img = ImageIO.read(url);
And that was the fix for my problem, now when I run the program images are now loaded.
Thank you so much!
I am using netbeans. I have a project directory like this:
HTMLEdit/
src/
htmledit/
- pic.png
- MyClass.java
I tried to get the image, but it return null. I had trying both of these but still cannot get it to work:
System.out.println(getClass().getResourceAsStream("/pic.png"));
and
System.out.println(getClass().getResourceAsStream("pic.png"));
What's causing this weird behavior?
EDIT :
It looks like it's because I choosed JAVAFX Project when created the project. I recreate the project by choosing Java Project and it works fine. May be this is Netbeans bug.
getClass().getResourceAsStream() is used for files embedded inside your java jar file. You should use FileInputStream if you need to read a file from your file system as a stream of bytes. Here's the documentation: https://docs.oracle.com/javase/8/docs/api/java/io/FileInputStream.html
When you do getClass().getResourceAsStream("/pic.png")then the url that will be looked to access the file will be an absolute url. The absolute URL is indicated by the slash which is at the front of the resource location.
If you do getClass().getResourceAsStream("pic.png"), then a resource relative to the package where the class resides will be used.
Because you said that both of the getResourceAsStream() statements did not work in Netbeans, I checked the below JavaFX code in Netbeans and it worked perfectly.
public class MyClass extends Application{
#Override
public void start(Stage primaryStage) {
Pane root = new Pane();
Image images = new Image(getClass().getResourceAsStream("pic.png"));
ImageView image = new javafx.scene.image.ImageView(images);
root.getChildren().add(image);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Here is the structure and the output of the program.
In case if you want to know the Netbeans version, I am using then it is Netbeans 8.0.2.
Also, read the following post.
Different ways of loading a file as an InputStream
just started a new project and am already running in to some issues. I am trying to display an image with javafx but the compiler is complaining that the provided location is invalid. Here is all of my code so far (apart from some imports):
public class main extends Application{
public static void main(String[] args) {
launch(args);
}
public void start(Stage primaryStage) throws Exception{
Stage stage = primaryStage;
String version = "alpha";
stage.setTitle("Space Invaders v. " + version);
VBox vbox = new VBox();
Image pic = new Image("Art\\whiteMonster.jpg");
ImageView image = new ImageView(pic);
vbox.getChildren().add(image);
Rectangle rect = new Rectangle(20,0,200,200);
rect.setFill(Color.BLACK);
vbox.getChildren().add(rect);
//Creating the scene.
Scene scene = new Scene(vbox);
stage.setScene(scene);
stage.show();
}
}
If I change the file path to the images url where I found it in google image search it displays the black rectangle added beneath it (just to test if everything works) but not the image. In the current configuration however it simply throws an error saying the URL is either invalid or that the resource was not found. What makes me think that this should work is this example here: https://docs.oracle.com/javase/8/javafx/api/javafx/scene/image/ImageView.html
Thanks for any help.
PS. I've been looking at other similar questions here but haven't found anything that helped me and if you feel like you need any other information give me a shout.
-----EDIT-----
Project Structure, Code and File Manager, all images are placed directly in the "Art" folder.
I hope that is all you need.
Try putting the image inside the folder .Drag the image to the "src" and use Image pic = new Image("whiteMonster.jpg");. It should be displayed under the .java files but a little bit in the left.
The solution for me was to Close Project and open the Javafx Project
again
as shown here
This refreshes the images URL for Javafx.
NOTE: I am using Intellij IDEA Java version 16 with Javafx.
Error was: Caused by: java.lang.IllegalArgumentException: Invalid URL or resource not found
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.
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.