Swing: Obter Imagem do JFrame

Como faço para obter um java.awt.Image de um JFrame?

Eu quero obter uma captura de canvas de um JFrame (para uso posterior em meu aplicativo). Isso é feito usando o robô para fazer uma captura de canvas especificando as coordenadas e dimensões do JFrame envolvido.

No entanto, acredito que exista uma maneira melhor: os componentes Swing, por padrão, se transformam em imagens como um buffer duplo antes de se pintarem na canvas.

Existe uma maneira de obter essas imagens do componente?

   

ComponentImageCapture.java

 import java.awt.BorderLayout; import java.awt.Component; import java.awt.Image; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.event.InputEvent; import javax.swing.*; import javax.swing.border.TitledBorder; import javax.imageio.ImageIO; import java.io.File; /** Create a screenshot of a component. @author Andrew Thompson */ class ComponentImageCapture { static final String HELP = "Type Ctrl-0 to get a screenshot of the current GUI.\n" + "The screenshot will be saved to the current " + "directory as 'screenshot.png'."; public static BufferedImage getScreenShot( Component component) { BufferedImage image = new BufferedImage( component.getWidth(), component.getHeight(), BufferedImage.TYPE_INT_RGB ); // call the Component's paint method, using // the Graphics object of the image. component.paint( image.getGraphics() ); // alternately use .printAll(..) return image; } public static void main(String[] args) { Runnable r = new Runnable() { public void run() { final JFrame f = new JFrame("Test Screenshot"); JMenuItem screenshot = new JMenuItem("Screenshot"); screenshot.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_0, InputEvent.CTRL_DOWN_MASK )); screenshot.addActionListener( new ActionListener(){ public void actionPerformed(ActionEvent ae) { BufferedImage img = getScreenShot( f.getContentPane() ); JOptionPane.showMessageDialog( null, new JLabel( new ImageIcon( img.getScaledInstance( img.getWidth(null)/2, img.getHeight(null)/2, Image.SCALE_SMOOTH ) ))); try { // write the image as a PNG ImageIO.write( img, "png", new File("screenshot.png")); } catch(Exception e) { e.printStackTrace(); } } } ); JMenu menu = new JMenu("Other"); menu.add(screenshot); JMenuBar mb = new JMenuBar(); mb.add(menu); f.setJMenuBar(mb); JPanel p = new JPanel( new BorderLayout(5,5) ); p.setBorder( new TitledBorder("Main GUI") ); p.add( new JScrollPane(new JTree()), BorderLayout.WEST ); p.add( new JScrollPane( new JTextArea(HELP,10,30) ), BorderLayout.CENTER ); f.setContentPane( p ); f.pack(); f.setLocationRelativeTo(null); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setVisible(true); } }; SwingUtilities.invokeLater(r); } } 

Captura de canvas

GUI com imagem capturada

Veja também

O código mostrado acima presume que o componente foi realizado na canvas, antes da renderização.

Rob Camick mostra como pintar um componente não realizado na class Screen Image .

Outro thread que pode ser relevante, é Render JLabel sem primeiro mostrar , particularmente o ‘one line fix’ de Darryl Burke.

LabelRenderTest.java

Aqui está uma variante atualizada do código mostrado no segundo link.

 import java.awt.*; import java.awt.image.BufferedImage; import javax.swing.*; public class LabelRenderTest { public static void main(String[] args) { SwingUtilities.invokeLater( new Runnable() { public void run() { String title = "" + "

Do UC Me?

" + "Here is a long string that will wrap. " + "The effect we want is a multi-line label."; JFrame f = new JFrame("Label Render Test"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); BufferedImage image = new BufferedImage( 400, 300, BufferedImage.TYPE_INT_RGB); Graphics2D imageGraphics = image.createGraphics(); GradientPaint gp = new GradientPaint( 20f, 20f, Color.red, 380f, 280f, Color.orange); imageGraphics.setPaint(gp); imageGraphics.fillRect(0, 0, 400, 300); JLabel textLabel = new JLabel(title); textLabel.setSize(textLabel.getPreferredSize()); Dimension d = textLabel.getPreferredSize(); BufferedImage bi = new BufferedImage( d.width, d.height, BufferedImage.TYPE_INT_ARGB); Graphics g = bi.createGraphics(); g.setColor(new Color(255, 255, 255, 128)); g.fillRoundRect( 0, 0, bi.getWidth(f), bi.getHeight(f), 15, 10); g.setColor(Color.black); textLabel.paint(g); Graphics g2 = image.getGraphics(); g2.drawImage(bi, 20, 20, f); ImageIcon ii = new ImageIcon(image); JLabel imageLabel = new JLabel(ii); f.getContentPane().add(imageLabel); f.pack(); f.setLocationByPlatform(true); f.setVisible(true); } }); } }

Captura de canvas

Rótulo processado na imagem