ruby how to load image relative to source code in jar - java

I have a jruby Swing application in a jar. In my source code main.rb I have an image specified as
img = ImageIcon.new("img/test.png")
which does not load. My path looks like this
lib/main.rb
lib/img/test.png
Is there a way to specify the relative path to the image?
In addition, I've found the equivalent way of doing this in Java using getResource
new javax.swing.ImageIcon(getClass().getResource("myimage.jpeg"))
How would I implement this in jruby?

Just like in Java - your file is not a file, it has to be addressed as a resource-inna-jar:
java.net.URL url = getClass().getResource("img/test.png");
ImageIcon image = new ImageIcon(url);
Didn't try, but translated into Ruby, I believe it's something like
url = JRuby.runtime.jruby_class_loader.get_resource("/lib/img/test.png")
image = ImageIcon.new(url)

Related

Java class.getRessource().getPath() adds a weird '/' at the begining of the URL

I want to load a font in a SWT. My ttf file is in the resources/fonts directory of my Maven project. I try to load it like this:
URL fontURL = MyClass.class.getResource("/fonts/myfont.ttf");
boolean fontLoaded = display.loadFont(fontURL.getPath());
But the resulting boolean is always false. I tried to prompt the result of fontURL.getPath(), and it is something like /C:/Users/myuser/Documents/.... If I copy this result in a String, remove the first / and try to call display.loadFont() with it, it works.
Another weird thing is that this is not the only resource I load this way. For example, this is how I load the icon of the window:
URL iconURL = MyClass.class.getResource("/images/myicon.png");
Image icon = new Image(display, iconURL.getPath());
shell.setImage(icon);
And it works fine. The only file posing problem is the font file. Does anybody know why ?
The reason for / at the beginning is that getPath of the URL class returns the URL path defined by RFC 2396 (see javadocs).
As for why it's working for the Image constructor and not for loadFont() method, the answer can be found in the implementation.
The constructor uses FileInputStream which internally normalizes the path, whereas loadFont() has a native implementation for loading which does not support such path.
Since in both cases a file path is expected, what you want to do is normalize the path yourself using either File constructor or Paths.get(url.toURI()).toString() method.

javafx - load image from within a jar

I'm sorry for asking such a beginner question, but I just can't get it to work and I can't find the answer anywere either.
I want to have an image inside my .jar file and load it. While that sounds simple, I was only able to load an image while running from inside the IDE but not anymore after making the .jar (Thanks to google I was able to get the .png inside the .jar). Here is what I tried:
BorderPane bpMain = new BorderPane();
String fs = File.separator;
Image imgManikin;
try {
imgManikin = new Image(
Main.class.getProtectionDomain().getCodeSource().getLocation().toURI().toString()+"\\manikin.png");
bpMain.setBottom(new Label(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI().toString()+"\\manikin.png"));
} catch (URISyntaxException e) {
imgManikin = new Image(
Main.class.getProtectionDomain().getCodeSource().getLocation().getPath()+"\\manikin.png");
System.out.println(Main.class.getProtectionDomain().getCodeSource().getLocation().getPath()+"\\manikin.png");
bpMain.setBottom(new Label(Main.class.getProtectionDomain().getCodeSource().getLocation().getPath()+"\\manikin.png"));
}
//Image imgManikin = new Image("file:src\\manikin.png");
ImageView imgvBackground = new ImageView(imgManikin);
imgvBackground.setFitWidth(100);
imgvBackground.setPreserveRatio(true);
bpMain.setCenter(imgvBackground);
primaryStage.setTitle("Kagami");
primaryStage.setScene(new Scene(bpMain, 300, 275));
primaryStage.show();
Needlessly to say it didn't work. It is showing me the Label at the bottom with the path just as intended, but it seams like the path just isn't right. (I also tried using the File.seperator instead of \\ and even /, but I got the same result every time: It showes me the path but won't load the image.
I'm using Windows 7, the IDE is IntelliJ and I have the newest Java update.
If the jar file is on the classpath of your application and the image to be loaded is located at the root of the jar file, the image can be loaded easily by:
URL url = getClass().getResource("/manikin.png");
BufferedImage awtImg = ImageIO.read(url);
Image fxImg = SwingFXUtils.toFxImage(awtImg, new Image());
Image fxImgDirect = new Image(url.openStream());
While ImageIO returns a BufferedImage this can be converted to a fx Image using the SwingUtils. However the preferred way is to directly create a new Image instance using the InputStream from the URL.
See also Load image from a file inside a project folder. If done right it does not matter if it is loaded from a jar file or the local file system.
The Image::new(String) constructor is looking for a URL. It is possible to construct a URL for a resource in a jar file, but it's much easier to use ClassLoader::getResource or ClassLoader::getResourceAsStream to manage that for you.
Given the file structure:
src/
SO37054168/
GetResourceTest.java
example/
foo.txt
The following, packaged as a jar will output
package SO37054168;
public class GetResourceTest {
public static void main(String[] args) {
System.out.println(GetResourceTest.class.getClassLoader().getResource("example/foo.txt"));
System.out.println(GetResourceTest.class.getClassLoader().getResourceAsStream("example/foo.txt"));
}
}
jar:file:/home/jeffrey/Test.jar!/example/foo.txt
sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream#7f31245a
Note how the URL for the resource is not the same as the URL you were trying to construct. The protocol is different, and you need to have the ! after the path to the jar file.

JButton image with different paths

I have added an icon to my JButton and the image is taken from a specific path inside my project files. But the problem is on another machine the path may be slightly different.
For instance my entire image path is home/jon/hello/folder/image.png, but on another machine the path may be /project/folder/william/hello/folder/image.png. Meaning the starting part of the path is different but from the hello part would be the same.
How can I make my path in my button code to be able to match the difference? My button code is below :
btn = new JButton(BUTTON_COLLAPSE_NESTED().toString());
btn.setIcon(newImageIcon("home/jon/hello/folder/image.png"));
btn.setActionCommand(BUTTON_COLLAPSE_NESTED().toString());
btn.addActionListener(btnListener);
btnPnl.add(btn);
This is why you shouldn't use absolute paths. Place the image in the jar, and use relative paths to resources, with the path based on the classpath to your class files.
For instance, if image.png is located in an images folder just off of the class file folder, you'd do something like:
URL url = getClass().getResource("/images/image.png");
BufferedImage img = ImageIO.read(url);
ImageIcon icon = new ImageIcon(img);
or something similar.

Getting icon from resources package (Java)

I'm trying to make a java program and have an application icon that is resources/Icon.png. My code at the moment is
ClassLoader cldr = this.getClass().getClassLoader();
URL url = cldr.getResource( "//resources//Icon.png" );
Toolkit kit = Toolkit.getDefaultToolkit();
Image img = kit.createImage(url);
this.setIconImage( img );
However I'm getting
Uncaught error fetching image: java.lang.NullPointerException
Am I referencing the location of the icon correctly? resources is a package in the program.
When using the ClassLoader to load a resource, the path must be a slash-separed path, not starting with a slash:
resources/Icon.png
If using the class directly (SomeClass.class.getResource(...)), then it can start with a slash to look for the resource by starting at the root of the classpath, or it can not start with a slash to look for the resource by starting at the same package as the class.
Not sure if this will fix it, but change your code so you're using a File and BufferedImage. Let me know if it doesn't.
Edit: Didn't see the bottom. Instead of URL, use a File.

Load Java Image inside package from a class in a different package

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.

Categories

Resources