动画GIF,显示在JPanel上,不是用paint方法在文件中截图,但JPG和PNG都可以
Animated GIF, displayed on JPanel, not screenshoting in file with paint method, but JPG and PNG are ok
不能使用 100% 真实代码,抱歉。其他 类 中的许多辅助功能,其中一些不是我的。
我正在制作视觉小说 - 只是评论一下我的项目,以便更好地理解。
我有一个带有 JPanel 卡片布局的 JFrame。 gameMainPanel 就是其中之一。我的目标 - 在拍摄时刻面板拍摄不可见的照片。在一个面板上是我的游戏绘图,在另一个面板上我正在制作游戏保存文件,其中包含游戏中的瞬间截图 - 所以游戏面板在那一刻不可见。它工作正常,但是当我在我的游戏面板上使用动画 GIF 时 - 它不是屏幕截图,而是所有其他 GUI 组件。
我正在使用如下代码加载动画 GIF 并调整其大小:
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 是一个小包装器,只是 returns 一个带有文件完整路径的字符串。 Engine.getPathString("/example/dummy.txt") 将 return 类似 "C:/Java projects/Folder with that project/example/dummy.txt" 的东西,当然是关于完全正确的路径。
一会儿我需要拍一张我的游戏面板,我是这样拍的:
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) {
}
并且该代码正确地截取了我的 gameMainPanel 及其所有子项的屏幕截图 - 游戏菜单、角色、带有文本的标签...但如果它们是动画 GIF,则不是角色。当我加载完全相同的代码时,一个简单的 *.jpg 或 *.png - 封顶正常。
为什么当我将其绘制为父级时,其中带有动画 GIF 的 JLabel 不可见,但当其中包含 JPG 时 - 它正常绘制到 BufferedImage?
无法提供项目的完整代码,抱歉。
英语不是我的母语,所以 - 也 - 对此也感到抱歉。
使用 PrintScreen 按钮制作:
使用游戏内方法制作:
所以,我进行了一个快速测试,基本上,我使用了 PNG 图像和动画 gif 图像,我使用 ImageIO
加载两者并尝试保存生成的面板,然后我使用 ImageIcon
加载图像并保存
我的意见...
PNG 图片
GIF 图片
"code"
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();
}
}
}
结果...
PNG 图片来自 ImageIO
GIF 图片来自 ImageIO
GIF 图片来自 ImageIcon
我不想深入了解这一切的原理和原因,不用说,ImageIcon
确实使用后台线程加载图像并依赖于 ImageObserver
的支持当状态发生变化时重新绘制的组件,这就是它如何在屏幕上更新动画 GIF,因此,有人可能会猜测我们只是缺少更新通知。
我没有测试过,但是你可以使用 MediaTracker
来监控 ImageIcon
的状态并等待它加载,但考虑到使用 ImageIO
的简单性我会质疑是否值得。
洞穴
如果您希望动画 gif 在实时组件上播放,您将需要使用 ImageIcon
!所以只能在生成预览的时候用这个"cheat"!
不能使用 100% 真实代码,抱歉。其他 类 中的许多辅助功能,其中一些不是我的。
我正在制作视觉小说 - 只是评论一下我的项目,以便更好地理解。
我有一个带有 JPanel 卡片布局的 JFrame。 gameMainPanel 就是其中之一。我的目标 - 在拍摄时刻面板拍摄不可见的照片。在一个面板上是我的游戏绘图,在另一个面板上我正在制作游戏保存文件,其中包含游戏中的瞬间截图 - 所以游戏面板在那一刻不可见。它工作正常,但是当我在我的游戏面板上使用动画 GIF 时 - 它不是屏幕截图,而是所有其他 GUI 组件。
我正在使用如下代码加载动画 GIF 并调整其大小:
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 是一个小包装器,只是 returns 一个带有文件完整路径的字符串。 Engine.getPathString("/example/dummy.txt") 将 return 类似 "C:/Java projects/Folder with that project/example/dummy.txt" 的东西,当然是关于完全正确的路径。
一会儿我需要拍一张我的游戏面板,我是这样拍的:
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) {
}
并且该代码正确地截取了我的 gameMainPanel 及其所有子项的屏幕截图 - 游戏菜单、角色、带有文本的标签...但如果它们是动画 GIF,则不是角色。当我加载完全相同的代码时,一个简单的 *.jpg 或 *.png - 封顶正常。
为什么当我将其绘制为父级时,其中带有动画 GIF 的 JLabel 不可见,但当其中包含 JPG 时 - 它正常绘制到 BufferedImage?
无法提供项目的完整代码,抱歉。 英语不是我的母语,所以 - 也 - 对此也感到抱歉。
使用 PrintScreen 按钮制作:
使用游戏内方法制作:
所以,我进行了一个快速测试,基本上,我使用了 PNG 图像和动画 gif 图像,我使用 ImageIO
加载两者并尝试保存生成的面板,然后我使用 ImageIcon
加载图像并保存
我的意见...
PNG 图片
GIF 图片
"code"
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();
}
}
}
结果...
PNG 图片来自 ImageIO
GIF 图片来自 ImageIO
GIF 图片来自 ImageIcon
我不想深入了解这一切的原理和原因,不用说,ImageIcon
确实使用后台线程加载图像并依赖于 ImageObserver
的支持当状态发生变化时重新绘制的组件,这就是它如何在屏幕上更新动画 GIF,因此,有人可能会猜测我们只是缺少更新通知。
我没有测试过,但是你可以使用 MediaTracker
来监控 ImageIcon
的状态并等待它加载,但考虑到使用 ImageIO
的简单性我会质疑是否值得。
洞穴
如果您希望动画 gif 在实时组件上播放,您将需要使用 ImageIcon
!所以只能在生成预览的时候用这个"cheat"!