Loading animated gif from JAR file into ImageIcon - java

I'm trying to create a ImageIcon from a animated gif stored in a jar file.
ImageIcon imageIcon = new ImageIcon(ImageIO.read(MyClass.class.getClassLoader().getResourceAsStream("animated.gif")));
The image loads, but only the first frame of the animated gif. The animation does not play.
If I load the animated gif from a file on the filesystem, everything works as expected. The animation plays through all the of frames. So this works:
ImageIcon imageIcon = new ImageIcon("/path/on/filesystem/animated.gif");
How can I load an animated gif into an ImageIcon from a jar file?
EDIT: Here is a complete test case, why doesn't this display the animation?
import javax.imageio.ImageIO;
import javax.swing.*;
public class AnimationTest extends JFrame {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
AnimationTest test = new AnimationTest();
test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
test.setVisible(true);
}
});
}
public AnimationTest() {
super();
try {
JLabel label = new JLabel();
ImageIcon imageIcon = new ImageIcon(ImageIO.read(AnimationTest.class.getClassLoader().getResourceAsStream("animated.gif")));
label.setIcon(imageIcon);
imageIcon.setImageObserver(label);
add(label);
pack();
} catch (Exception e) {
e.printStackTrace();
}
}
}

This reads gif animation from inputStream
InputStream in = ...;
Image image = Toolkit.getDefaultToolkit().createImage(org.apache.commons.io.IOUtils.toByteArray(in));

You have to use getClass().getResource(imgName); to get a URL to the image file. Check out this tutorial from Real's HowTo.
EDIT: Once the image is loaded you have to set the ImageObserver property to get the animation to run.

Since this thread was just linked from a more current thread that had little to do with animated GIFs but got dragged OT, I thought I'd add this trivial source that 'works for me'.
import javax.swing.*;
import java.net.URL;
class AnimatedGifInLabel {
public static void main(String[] args) throws Exception {
final URL url = new URL("http://i.stack.imgur.com/OtTIY.gif");
Runnable r = new Runnable() {
public void run() {
ImageIcon ii = new ImageIcon(url);
JLabel label = new JLabel(ii);
JOptionPane.showMessageDialog(null, label);
}
};
SwingUtilities.invokeLater(r);
}
}

Hopefully it's not too late for this.
I managed to get the animated gif inside my JPanel this way:
private JPanel loadingPanel() {
JPanel panel = new JPanel();
BoxLayout layoutMgr = new BoxLayout(panel, BoxLayout.PAGE_AXIS);
panel.setLayout(layoutMgr);
ClassLoader cldr = this.getClass().getClassLoader();
java.net.URL imageURL = cldr.getResource("img/spinner.gif");
ImageIcon imageIcon = new ImageIcon(imageURL);
JLabel iconLabel = new JLabel();
iconLabel.setIcon(imageIcon);
imageIcon.setImageObserver(iconLabel);
JLabel label = new JLabel("Loading...");
panel.add(iconLabel);
panel.add(label);
return panel;
}
Some points of this approach:
1. The image file is within the jar;
2. ImageIO.read() returns a BufferedImage, which doesn't update the ImageObserver;
3. Another alternative to find images that are bundled in the jar file is to ask the Java class loader, the code that loaded your program, to get the files. It knows where things are.
So by doing this I was able to get my animated gif inside my JPanel and it worked like a charm.

Related

Images not visible in JList

I'm writing a little photo application (asked some questions before) and I have one problem which I cannot resolve. The idea is that there are two sections: the upper one is for an overview (using thumbnails) and the lower one shows the selected image in it's full size. I cannot use ImageIO (required by my lecturer).
I'm using a JList for the overview but most images are not visible. I chose a folder with about 20 images and only 2 show up. And one of them isn't even centered.
For some reason, if I delete those lines:
thumbnaillist.setFixedCellWidth(thumbW);
thumbnaillist.setFixedCellHeight(thumbH);
One image shows up that wasn't visible before, but now the other two disappear.
This is my code:
public class PVE extends JFrame {
private JFileChooser fileChoose;
//MenuBar
private JMenuBar menubar;
private JMenu file;
private JMenuItem openFolder;
private JMenuItem exit;
//Thumbnails
private JList thumbnaillist;
private DefaultListModel<ImageIcon> listmodel;
private JScrollPane tscroll;
private ImageIcon thumbs;
private int thumbW = 100;
private int thumbH = 100;
//for full size view
private JPanel imgview;
public PVE() {
setLayout(new BorderLayout());
//MenuBar
menubar = new JMenuBar();
file = new JMenu("File");
openFolder = new JMenuItem("Open folder...");
exit = new JMenuItem("Quit");
file.add(openFolder);
file.addSeparator();
file.add(exit);
menubar.add(file);
setJMenuBar(menubar);
fileChoose = new JFileChooser();
openFolder.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
fileChoose.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fileChoose.showOpenDialog(null);
File chosenDir = fileChoose.getSelectedFile();
loadToThumbView(chosenDir);
}
});
//Thumbnail view
listmodel = new DefaultListModel();
thumbnaillist = new JList(listmodel);
thumbnaillist.setLayoutOrientation(JList.HORIZONTAL_WRAP);
thumbnaillist.setFixedCellWidth(thumbW);
thumbnaillist.setFixedCellHeight(thumbH);
thumbnaillist.setVisibleRowCount(1);
tscroll = new JScrollPane(thumbnaillist, JScrollPane.VERTICAL_SCROLLBAR_NEVER,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
tscroll.setPreferredSize(new Dimension(0, 100));
add(tscroll, "North");
//for full size view
imgview = new JPanel();
imgview.setBackground(Color.decode("#f7f7f7"));
add(imgview, "Center");
setTitle("Photo Viewer");
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
SwingUtilities.updateComponentTreeUI(this);
} catch (Exception e) {
}
setSize(700, 700);
setLocation(200, 200);
setVisible(true);
}
public void loadToThumbView(File folder) {
listmodel.removeAllElements();
File[] imgpaths = folder.listFiles();
for (int j = 0; j < imgpaths.length; j++) {
listmodel.addElement(resizeToThumbnail(new ImageIcon(imgpaths[j].toString())));
}
}
public ImageIcon resizeToThumbnail(ImageIcon icon) {
Image img = icon.getImage();
BufferedImage bf = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics g = bf.createGraphics();
g.drawImage(img, 0, 0, thumbW, thumbH, null);
ImageIcon kB = new ImageIcon(bf);
return kB;
}
public static void main(String argv[]) {
PVE pv = new PVE();
}
}
Your problem is because of the way you're scaling your images.
I'm not exactly sure why but I guess it has something to do with the BufferedImage#createGraphics() call and that I was able to reproduce the problem with .jpg images while .png files were correctly painted.
However if you scale your images instead of converting them to a BufferedImage and getting a new ImageIcon from it, you get the correct output:
public ImageIcon resizeToThumbnail(ImageIcon icon) {
Image img = icon.getImage();
Image scaled = img.getScaledInstance(thumbW, thumbH, Image.SCALE_SMOOTH);
return new ImageIcon(scaled);
}
This is the folder I used to test:
And the outputs with your code and mine:
Important notes
And as as a recommendation don't make a window that big if all you're using is that little bar above. If you're adding something else below, then it's ok but for now it's not that "user friendly" (IMHO). Instead of JFrame#setSize() you could try using JFrame#pack() method so your frame resizes to it's preferred size.
Some other things I noted in your program:
You're not placing it inside the Event Dispatch Thread (EDT) which is dangerous since your application won't be Thread safe that way. You can change that if you change your main method as follows:
public static void main(String argS[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
PVE pv = new PVE();
}
});
}
You're setting the JScrollPane preferred size, instead you should override its getPreferredSize() method, see Should I avoid the use of setPreferred|Maximum|MinimumSize methods in Java Swing? (YES)
You're extending JFrame, you should instead create an instance of it unless you're overriding one of its methods (and you're not, so don't do it) or you have any good reason to do it. If you need to extend a Container you should extend JPanel instead, as JFrame is a rigid container which cannot be placed inside another one. See this question and this one.
I think I'm not missing anything, and hope this helps
Your “scaled” images are actually images which are the same size as the original image, but are blank except for a scaled version drawn in the upper left corner. That upper left corner is clipped out of view in each rendered cell (at least for the somewhat large images I tested with).
The scaled image needs to be created with the thumbnail size, not the size of the original image. Meaning, change this:
BufferedImage bf = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
to this:
BufferedImage bf = new BufferedImage(thumbW, thumbH, BufferedImage.TYPE_INT_ARGB);

Trying to add an image to a label but won't work?

I'm trying to add the image "Pic.png" to this JLabel "label1" and display it on the JPanel "panel1" on a JFrame "window1". But it when I hit run it doesn't display my image. Anyone help? (I read about adding it to the source file or something but I'm not really sure what I'm doing because I'm new to Java. Will it not be able to access the picture without the image being in the source?)
public class UIForIshidaQuery {
public static void main(String[] args) {
System.out.println("Running...");
JFrame window1 = new JFrame();
window1.setVisible(true);
window1.setSize(1080, 720);
window1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel1 = (JPanel) window1.getContentPane();
JLabel label1 = new JLabel();
panel1.setLayout(null);
ImageIcon image = new ImageIcon("C:\\Users\\BC03\\Pictures\\Saved Pictures\\Other\\Pic.png");
label1.setIcon(image);
label1.setBounds(500, 500, 500, 500);
panel1.add(label1);
}
}
The window should be set visible as the last call. Don't use null layouts1. This works.
import java.net.*;
import javax.swing.*;
public class UIForIshidaQuery {
public static String url = "http://i.stack.imgur.com/gJmeJ.png";
public static void main(String[] args) throws MalformedURLException {
System.out.println("Running...");
JFrame window1 = new JFrame();
window1.setSize(1080, 720);
window1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel1 = (JPanel) window1.getContentPane();
JLabel label1 = new JLabel();
//panel1.setLayout(null);
ImageIcon image = new ImageIcon(new URL(url));
label1.setIcon(image);
//label1.setBounds(500, 500, 500, 500);
panel1.add(label1);
window1.setVisible(true);
}
}
Java GUIs have to work on different OS', screen size, screen resolution etc. using different PLAFs in different locales. As such, they are not conducive to pixel perfect layout. Instead use layout managers, or combinations of them along with layout padding and borders for white space.
If you are using IntelliJ IDEA:
Right click your project root directory and select New > Directory;
Call the new directory 'resources' for example;
Right click the newly made directory and select Mark Directory As > Resources Root;
Add your image file in the directory;
Access your file properly:
CurrentClass.class.getClassLoader().getResource("pic.png").getFile();
The ImageIcon could be initialized like this:
File file = new File(CurrentClass.class.getClassLoader().getResource("pic.png").getFile());
BufferedImage image = null;
try {
image = ImageIO.read(file);
} catch (IOException e) {
e.printStackTrace();
}
ImageIcon imageIcon = new ImageIcon(image);

ImageIcon does not work with me

i wrote very simple code to display an icon of the grapes but still the code doesn't show me anything
here is my code
import javax.swing.*;
import java.awt.*;
public class Code {
ImageIcon ii = new ImageIcon("image/grapes2.jpg");
JLabel label = new JLabel("Grapes", ii, SwingConstants.CENTER);
JFrame frame = new JFrame("ImageIcon");
public void ui(){
label.setHorizontalTextPosition(SwingConstants.CENTER);
label.setVerticalTextPosition(SwingConstants.BOTTOM);
label.setIconTextGap(5);
label.setOpaque(true);
label.setBackground(Color.GRAY);
frame.setSize(2300,2300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(label);
}
}
If image icon is not visible even after calling frame.setVisible(true) in the end then have a look at my another posts that is asked in the same context.
How to retrieve image from project folder?
Read image from another directory
Try
// Read from src/image folder
ii = new ImageIcon(ImageIO.read(getClass().getResource("/image/grapes2.jpg")));
label.setIcon(ii);
It's worth reading How to Use Icons and here is the sample directly from there.
ImageIcon icon = createImageIcon("images/middle.gif",
"a pretty but meaningless splat");
label1 = new JLabel("Image and Text", icon, JLabel.CENTER);
...
label3 = new JLabel(icon);
/** 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;
}
}
Read more Loading Images Using getResource where it is explained visually.
For e.g. Class file in directory named omega. Image in omega/images directory.

Java adding ImageIcon to JLabel

I am trying to make a very basic game with Java and I am having trouble displaying an image on a JFrame. It has worked in the past for me and now is not, i can't see what I did wrong.
I have tried printing the current working directory and changing where I get my image to match that. It is likely that the problem is not getting the image, since my (filefinder or filereader or something like that) can find it without problems, but I cannot correctly add it (the ImageIcon) to the JLabel, or that to the JFrame.
This is my code...
JFrame frame = new JFrame("no image");
ImageIcon image = new ImageIcon("C:/Documents and Settings/user/Desktop/hi/xD/JavaApplication2/image.png");
JLabel imagelabel = new JLabel(image);
frame.add(imagelabel);
The JFrame has been setVisible(true) and pack().
Could someone please help me understand what is wrong.
Your problem lies here:
ImageIcon image = new ImageIcon("C:/Documents and Settings/user/Desktop/hi/xD/JavaApplication2/image.png");
JLabel imagelabel = new JLabel(character);
You create an ImageIcon "image" but you create your JLabel with "character".
It should be:
JLabel imagelabel = new JLabel(image);
Try,
ImageIcon image = new ImageIcon("c:\\path\\image.png");
imagelabel = new JLabel(character, image, JLabel.CENTER);
frame.add(imagelabel);
Take a look at Tutorial - How to use Icons
import javax.awt.*;
import java.awt.*;
import java.awt.event*;
//class name image
class image {
image()
//constructor {
Frame f=new Frame("Image");
//Frame
f.setSize(500,500);
f.setVisible(true);
Panel p =new Panel();
//Panel
f.add(p);
p.addLayout(null);
ImageIcon ii=new ImageIcon("set your image path");
//ImageIcon is used to image Display .
Label l =new Label(ii);
p.add(ii);
p.setBounds(set you bounds);
//Like that(20,20,500,40);
}
public static void main(String [] args) {
image obj = new
}
}

Displaying an image in Java Swing

public class MinesweeperMenu extends MinesweeperPanel{
private JPanel picture = new JPanel();
private JButton play = new JButton("Play");
private JButton highScores = new JButton("High Score and \nStatistics");
private JButton changeMap = new JButton("Create Custom \nor Change Map");
private JButton difficulty = new JButton("Custom or\nChange Difficulty");
private JButton user = new JButton("Change User");
Image img;
public MinesweeperMenu()
{
// Set Layout for the menu
LayoutManager menuLayout = new BoxLayout(menu, BoxLayout.Y_AXIS);
menu.setLayout(menuLayout);
// Set Layout for the window
LayoutManager windowLayout = new BorderLayout();
window.setLayout(windowLayout);
// Add buttons to the panels
menu.add(play);
menu.add(highScores);
menu.add(changeMap);
menu.add(difficulty);
menu.add(user);
// Add picture to the frame
try{
File input = new File("./setup/images/MineMenuPicture.jpg");
img = ImageIO.read(input);
}
catch(IOException ie)
{
System.out.println(ie.getMessage());
}
// Add action listeners
changeMap.addActionListener(new ChangeMapListener());
}
public void paintComponent(Graphics g)
{
// POSITION OF THE PICTURE
int x = 650;
int y = 585;
g.drawImage(img, x, y, null);
}
public void displayFrame()
{
// Display Frame
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
}
public static void main(String[] args)
{
MinesweeperMenu menu = new MinesweeperMenu();
window.pack();
menu.displayFrame();
window.repaint();
}
}
public class MinesweeperPanel extends JFrame{
public static final Color COLOR_KEY = new Color(220, 110, 0);
// Initialize all the objects
public static JFrame window = new JFrame("Minesweeper++");
public static JPanel menu = new JPanel();
// Close the current window
public static void close()
{
window.setVisible(false);
window.dispose();
}
}
I can't get my image to display in the frame. I've tried everything, but I'm getting the impression it's a mistake that I'm not realizing since I am new to Java Swing. Any help would be greatly appreciated.
You're making things difficult for yourself by having a very confusing program structure, and I suggest that you simplify things a lot.
For one, there's no need for your current MinesweeperMenu class to extend MinesweeperPanel, and for the latter class to extend JFrame. Then you have a static JFrame somewhere else -- that's too many JFrames, and to boot, you're trying to display your image in one JFrame but showing the other one that doesn't have the picture. Your program needs just one JFrame and it should probably be created, stuffed with its contents, packed and displayed in one place, not scattered here and there as you're doing.
You're trying to display the picture in a paintComponent override, but this method will never get called since your class extends JFrame (eventually) and JFrame doesn't have this method. You're using the right method, but the class should be extending JPanel, and you should have an #Override annotation above the paintComponent method block to be sure that you're actually overriding a parent method.
You should get rid of all static everything in this program. The only thing static here should be the main method and perhaps some constants, but that's it.
There are more errors here, and I have too little time to go over all of them. Consider starting from the beginning, starting small, getting small bits to work, and then adding them together.
For instance, first create a very small program that tries to read in an image into an Image object, place it in a ImageIcon, place the ImageIcon into a JLabel, and display the JLabel in a JOptionPane, that simple, just to see if you can read in images OK, for example, something like this:
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
public class TestImages {
// *** your image path will be different *****
private static final String IMG_PATH = "src/images/image01.jpg";
public static void main(String[] args) {
try {
BufferedImage img = ImageIO.read(new File(IMG_PATH));
ImageIcon icon = new ImageIcon(img);
JLabel label = new JLabel(icon);
JOptionPane.showMessageDialog(null, label);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Then when you've done this, see if you can now create a JPanel that shows the same Image in its paintComponent method, and display this JPanel in a JOptionPane.
Then create a JFrame and display the image-holding JPanel in the JFrame.
Through successive iterations you'll be testing concepts, correcting mistakes and building your program.
File input = new File("./setup/images/MineMenuPicture.jpg");
If MineMenuPicture.jpg is an application resource, it should be in a Jar and accessed by URL obtained from Class.getResource(String).

Categories