Component
有一个方法paintAll(Graphics)
(你已经找到了)。该方法将在传递的图形上绘制自己。但是我们必须在调用paint方法之前预先配置图形。这就是我在java.sun.com上发现的关于 AWT 组件渲染的内容:
当 AWT 调用此方法时,Graphics 对象参数会预先配置适当的状态以在此特定组件上绘图:
- Graphics 对象的颜色设置为组件的前景属性。
- Graphics 对象的字体设置为组件的字体属性。
- Graphics 对象的平移设置为坐标 (0,0) 表示组件的左上角。
- Graphics 对象的剪辑矩形设置为需要重新绘制的组件区域。
所以,这是我们得到的方法:
public static BufferedImage componentToImage(Component component, Rectangle region)
{
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);
g.dispose();
if (region == null)
{
return img;
}
return img.getSubimage(region.x, region.y, region.width, region.height);
}
这也是比使用Robot
可见组件更好的方法。
编辑:
很久以前,我使用了我在上面发布的代码,它有效,但现在不行。所以我进一步搜索。我有一个经过测试的工作方式。它很脏,但有效。它的想法是制作一个 JDialog,将其放在屏幕边界之外的某个位置,将其设置为可见,然后将其绘制在图形上。
这是代码:
public static BufferedImage componentToImageWithSwing(Component component, Rectangle region) {
BufferedImage img = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = img.createGraphics();
// Real render
if (component.getPreferredSize().height == 0 && component.getPreferredSize().width == 0)
{
component.setPreferredSize(component.getSize());
}
JDialog f = new JDialog();
JPanel p = new JPanel();
p.add(component);
f.add(p);
f.pack();
f.setLocation(-f.getWidth() - 10, -f.getHeight() -10);
f.setVisible(true);
p.paintAll(g);
f.dispose();
// ---
g.dispose();
if (region == null) {
return img;
}
return img.getSubimage(region.x, region.y, region.width, region.height);
}
因此,这也适用于 Windows 和 Mac。另一个答案是在虚拟屏幕上绘制它。但这不需要它。