Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何将每个paintComponent调用同时写入BuffereImage?_Java_Swing_Awt_Bufferedimage_Paintcomponent - Fatal编程技术网

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中的每一个动画都包含了程序员的答案/评论,并链接到他的代码,这不是唯一被调用的吗