Can't use 100% real code, sorry. A lot of side-functions in other classes, some of them isn't mine.
I'm making a visual novel - just remark about my project, for better undestanding.
I have a JFrame with card layout of JPanels. gameMainPanel are one of them. My target - make a shot of non-visible at shoting moment panel. On one panel is my game drawing, on another I'm making game-savefile with screenshot of moment in game - so game panel isn't visible at that moment. It's working OK, but when I use an animated GIF on my game panel - it's not screenshoting, but every other GUI components do.
I'm loading and resizing an animated GIF with code like this:
ImageIcon imageIcon = new ImageIcon(Engine.getPathString("/resource/character/" + name));
imageIcon.setImage(imageIcon.getImage().getScaledInstance(resizeX, resizeY, Image.SCALE_DEFAULT));
GameWindow.gameCharacterCenter.setIcon(imageIcon); //gameCharacterCenter is a simple JLabel on game panel
Engine.getPathString is a little wrapper, just returns a string with full path to file. Engine.getPathString("/example/dummy.txt") will return something like "C:/Java projects/Folder with that project/example/dummy.txt", regarding full correct path of course.
In one moment I need to make a shot of my game panel, I'm making it like this:
screenshot = new File(String.valueOf(Engine.getPathFile("/saves/" + name + ".jpeg")));
BufferedImage bufImage = new BufferedImage(GameWindow.gameMainPanel.getSize().width, GameWindow.gameMainPanel.getSize().height, BufferedImage.TYPE_INT_RGB);
GameWindow.gameMainPanel.paint(bufImage.createGraphics());
try {
screenshot.createNewFile();
ImageIO.write(bufImage, "jpeg", screenshot);
} catch (Exception ex) {
}
And that code is correctly screenshoting my gameMainPanel, with all it's childs - game menu, characters, labels with text... But not the characters if they are animated GIFs. When I'm loading with exact same code a simple *.jpg or *.png - it's capping OK.
Why are JLabel with animated GIF in it isn't visible when I'm painting it parent, but when it's JPG in it - it's paint to BufferedImage as normal?
Can't provide full code of project, sorry. English not my native, so - also - sorry for that too.
Made with PrintScreen button:
Made with ingame methods:
So, I put together a quick test, basically, I took a PNG image a animated gif image, I used ImageIO
to load both and attempted to save the resulting panel and then I used ImageIcon
to load the image and save it
My inputs...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
BufferedImage png = ImageIO.read(...));
BufferedImage gif = ImageIO.read(...);
ImageIcon gifImg = new ImageIcon(...);
TestPane pngPane = new TestPane(png);
TestPane gifPane = new TestPane(gif);
TestPane imgPane = new TestPane(gifImg.getImage());
save(pngPane, "PNGTest.png");
save(gifPane, "gifTest.png");
save(imgPane, "imgGifTest.png");
} catch (IOException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public void save(JPanel pane, String to) throws IOException {
pane.setSize(pane.getPreferredSize());
BufferedImage img = new BufferedImage(pane.getWidth(), pane.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = img.createGraphics();
pane.printAll(g2d);
g2d.dispose();
ImageIO.write(img, "png", new File(to));
}
public class TestPane extends JPanel {
private Image img;
public TestPane(Image img) {
this.img = img;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(img.getWidth(this), img.getHeight(this));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(img, 0, 0, this);
g2d.dispose();
}
}
}
ImageIO
ImageIO
ImageIcon
I don't want to get into the hows and whys of it all, needless to say, ImageIcon
does use a background thread to load the image and relies on the ImageObserver
support of the component to get it repainted as it's state changes, this is how it gets the animated GIF to update on the screen, so, one might surmise that we're just missing that update notification.
I've not tested it, but you could use a MediaTracker
to monitor the ImageIcon
's state and wait till it's loaded, but given the simplicity of using ImageIO
I'd question whether it's worth it or not.
You will need to use ImageIcon
if you want the animated gif to play on a live component! So you can only use this "cheat" when generating the preview!