如何在Java中从组件获取BufferedImage?

6
我知道如何从JComponent获取BufferedImage,但是如何从java中的Component获取BufferedImage呢?这里重点是"Component"类型的对象而不是JComponent。
我尝试了下面的方法,但它返回的是全黑的图像,有什么问题吗?
  public static BufferedImage Get_Component_Image(Component myComponent,Rectangle region) throws IOException
  {
    BufferedImage img = new BufferedImage(myComponent.getWidth(), myComponent.getHeight(), BufferedImage.TYPE_INT_RGB);
    Graphics g = img.getGraphics();
    myComponent.paint(g);
    g.dispose();
    return img;
  }

1
“从JComponent获取BufferedImage”是什么意思? - aioobe
看看我的新答案,现在它可以正常工作了。(已测试) - Martijn Courteaux
2个回答

8

Component有一个方法paint(Graphics)。这个方法会在传入的Graphics上绘制自身。这是我们要用来创建BufferedImage的方法,因为BufferedImage有一个方便的方法getGraphics()。它返回一个Graphics对象,你可以用它来绘制BufferedImage

更新:但我们必须预先配置好绘图方法的图形属性。这就是我在java.sun.com上找到的有关AWT Component渲染的信息:

当AWT调用此方法时,
Graphics对象参数已经预先配置了适用于在此特定组件上进行绘图的状态:

  • Graphics对象的颜色设置为组件的前景色属性。
  • Graphics对象的字体设置为组件的字体属性。
  • Graphics对象的平移被设置为坐标(0,0),表示组件的左上角。
  • Graphics对象的剪辑矩形被设置为需要重新绘制的组件区域。

所以,这是我们得到的方法:

public static BufferedImage componentToImage(Component component, Rectangle region) throws IOException
{
    BufferedImage img = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TYPE_INT_ARGB_PRE);
    Graphics g = img.getGraphics();
    g.setColor(component.getForeground());
    g.setFont(component.getFont());
    component.paintAll(g);
    if (region == null)
    {
        region = new Rectangle(0, 0, img.getWidth(), img.getHeight());
    }
    return img.getSubimage(region.x, region.y, region.width, region.height);
}

1
这与您为“组件”执行的方式有何不同?我认为这个问题需要一些澄清。 - aioobe
我试过了,但还是没有起作用,可能因为我传递给它的组件是来自JDIC的WebBrowser对象,这是一个非轻量级的组件,正如我在我的其他问题中提到的那样,你知道如何使它工作吗?有人建议我使用CellRenderPane,但我不知道如何在我的情况下使用它,有示例代码吗? - Frank
@DavidKroukamp 我认为这并不是一个很好的答案。创建具有固定属性的 BufferedImage 可能意味着它的处理比必要的要慢得多。此外,虽然 Q 要求使用 BufferedImage,但更改可能只需要一个 Image。为什么不简单地使用 Component.createImage() - class stacker
虽然我在获取子区域方面可能更聪明,但这对我起作用了。 img = new BufferedImage(region.width,region.height,...); Graphics2D g = img.createGraphics(); g.translate(-region.x,-region.y); component.paintAll(g);我确信Java基于剪辑边界优化渲染,这应该是图像的大小;它至少跳过了getSubimage步骤。 - Perry Monschau

1

我同意您的观点,Q的意图尚未明确。如果您提到了特定的用例,那就更好了,这样可以让人知道您的答案适用于哪种情况。 - class stacker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接