Component
имеет метод paintAll(Graphics)
(как вы уже нашли). Этот метод будет рисовать себя на переданной графике. Но нам нужно предварительно настроить графику, прежде чем мы вызовем метод рисования. Вот что я нашел о рендеринге компонентов AWT на java.sun.com :
Когда AWT вызывает этот метод,
Параметр графического объекта
предварительно настроенный с соответствующим
состояние для рисования на этом конкретном
компонент:
- Цвет объекта 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
для видимых компонентов.
EDIT:
Давным-давно я использовал код, который выложил здесь выше, и он работал, но сейчас нет. Поэтому я искал дальше. У меня есть проверенный, рабочий способ. Это грязно, но работает. Идея в том, чтобы создать 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. Другим ответом было нарисовать его на виртуальном экране. Но это не нужно.