Java 如何将每个paintComponent调用同时写入BuffereImage?
如何通过Java 如何将每个paintComponent调用同时写入BuffereImage?,java,swing,awt,bufferedimage,paintcomponent,Java,Swing,Awt,Bufferedimage,Paintcomponent,如何通过JPanel-类型(即扩展/从JPanel继承的自定义类)将每次重绘调用(直接或非直接)写入缓冲区图像 在自定义类“paintComponent中执行此类操作不起作用: protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D G2 = (Graphics2D) g; // ... draw objects BufferedImage imageBu
JPanel
-类型(即扩展/从JPanel
继承的自定义类)将每次重绘调用(直接或非直接)写入缓冲区图像
在自定义类“paintComponent
中执行此类操作不起作用:
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D G2 = (Graphics2D) g;
// ... draw objects
BufferedImage imageBuffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
G2 = imageBuffer.createGraphics();
// Which doesn't work, because with that method it seems you would
// need to call paint() on Graphics2D reference here.
// And to do so would then throw an Illegal Exception.
}
生成的buffereImage
是调用paintComponent
的JPanel
类型类的正确大小,但是图像是黑色的(即空的)-这是完全合乎逻辑的,因为createGraphics()
本身不起任何作用
我知道Rob Camick的代码,但这似乎是为程序初始化时的一个屏幕截图设计的
让我困惑的是,paintComponent
的功能必须保存在内存中,然后才能显示在屏幕上。。。因此,是否有一种方法可以每次捕获该图像并将其保存到BufferedImage
中?您必须在组件的绘制函数之外创建BufferedImage
,然后使用BufferedImage
图形作为参数调用此绘制函数
BufferedImage imageBuffer = new BufferedImage(comp.getWidth(), cmp.getHeight(), BufferedImage.TYPE_INT_RGB);
cmp.paint(imageBuffer.getGraphics());
这种方法怎么样?与发布代码不同的是,您需要在buffereImage
上进行所有自定义绘图。然后,只在组件上绘制一个对象:BufferedImage
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
BufferedImage imageBuffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics imageG2 = imageBuffer.createGraphics();
// do custom painting onto imageG2...
// save imageBuffer
g2.drawImage(imageBuffer, 0, 0, this); // draw onto component
}
描述和一些细节可能并不完全清楚。但基本上听上去,您希望创建一个可以像普通JPanel
一样使用的组件,但是paintComponent
方法中绘制的所有内容也应该保存为BufferedImage
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
BufferedImage imageBuffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics imageG2 = imageBuffer.createGraphics();
// do custom painting onto imageG2...
// save imageBuffer
g2.drawImage(imageBuffer, 0, 0, this); // draw onto component
}
对此有不同的解决方案。你可以打专门的电话,比如
myComponent.paintComponent(bufferedImageGraphics);
并按照一个答案中的建议相应地处理图像。另一个答案建议创建一个自定义的paintComponent
方法来处理图像
但是,我想提出以下解决方案:您可以创建一个扩展JPanel
的ImageSavingComponent
类。在这个类中,您不重写paintComponent
方法,而是重写paint
方法。paint
方法完成两件事:
- 它调用
super.paint(bufferedImageGraphics)
,将图像绘制成一幅图像
- 它调用
super.paint(componentGraphics)
,在屏幕上绘制
通过这种方式,您可以简单地扩展这个类,并实现paintComponent
方法,就像您对任何JPanel
所做的那样。图像处理可以完全透明地完成
在下面的示例中,我添加了一个消费者
界面,用于接收图像并进行适当处理。如果消费者
为空
,则不会生成图像。为了测试,我创建了这个接口的一个实现,它只需每隔200毫秒将图像存储在文件中。(如果需要,此接口可替换为Java 8<代码>消费者
接口)
导入java.awt.Color;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.image.buffereImage;
导入java.io.FileOutputStream;
导入java.io.IOException;
导入javax.imageio.imageio;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JToggleButton;
导入javax.swing.SwingUtilities;
导入javax.swing.Timer;
公共类ImageSavingComponentTest{
公共静态void main(字符串[]args){
SwingUtilities.invokeLater(新的Runnable(){
@凌驾
公开募捐{
createAndShowGUI();
}
});
}
私有静态void createAndShowGUI(){
JFrame f=新的JFrame();
f、 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
最终ImageSavingComponent c=新示例ImageSavingComponent();
f、 getContentPane()。添加(c);
最终计时器=新计时器(50,新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
c、 重新油漆();
}
});
timer.start();
最终消费者您是否可以使用自己的Graphics
在BufferedImage
上进行自定义绘制,保存它,然后使用paintComponent()在组件上创建BufferedImage
Graphics?这完全是可行的。简单直接的解决方案,谢谢。这是一个非常宽泛的答案,很抱歉我不能接受多个答案。@BenjaminR没问题。我接受的答案似乎与您最初要求的完全不同,但当您对它感到满意时,显然正是您想要的答案你一直在寻找。然而,如果这是你一直在寻找的,你的问题确实是重复的。我不知道……你对我问题的解释似乎是用威士忌皮德的答案最有效的回答。只是为了掩盖我的背后而勾选你的答案感觉是错误的,所以如果这个问题需要标记,我宁愿接受对重复答案的点击比不光彩的多…不过再次感谢。我希望看到准确的重复,因为我使用了问题主题行的准确关键字。也许这就是问题/歧义?也许应该是“如何将每个paintComponent调用同时写入BuffereImage?”--这似乎与问题文本更为一致。@BenjaminR当然,我可能高估了一些陈述或做出了隐含的假设。再说一次:我这边没有问题。JPanel是ImageObserver,请为Swing JComponent?画图,超级。画图(g)应该是标准代码中的第一行代码,基本上去年JavaSwing中的每一个动画都包含了程序员的答案/评论,并链接到他的代码,这不是唯一被调用的吗