Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swing: Obtain Image of JFrame

How do I obtain a java.awt.Image of a JFrame?

I want to obtain a screen shot of a JFrame (for later use within my application). This is presently accomplished using the robot to take a screen shot specifying the coordinates and dimensions of the JFrame involved.

However, I believe that there is a better way: Swing components, by default, render themselves as images into a double buffer prior to painting themselves onto the screen.

Is there a way to obtain these images from the component?

like image 473
bguiz Avatar asked May 02 '11 05:05

bguiz


People also ask

What does pack () do in Swing?

The pack method sizes the frame so that all its contents are at or above their preferred sizes. An alternative to pack is to establish a frame size explicitly by calling setSize or setBounds (which also sets the frame location).

Does JFrame contain Swing?

The JFrame class is slightly incompatible with Frame . Like all other JFC/Swing top-level containers, a JFrame contains a JRootPane as its only child. The content pane provided by the root pane should, as a rule, contain all the non-menu components displayed by the JFrame . This is different from the AWT Frame case.


1 Answers

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);   } }  

Screen shot

GUI with captured image

See also

The code shown above presumes the component has been realized on-screen, prior to rendering.

Rob Camick shows how to paint an unrealized component in the Screen Image class.

Another thread that might be of relevance, is Render JLabel without 1st displaying, particularly the 'one line fix' by Darryl Burke.

LabelRenderTest.java

Here is an updated variant of the code shown on the second 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 = "<html><body style='width: 200px; padding: 5px;'>"                 + "<h1>Do U C Me?</h1>"                 + "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);             }         });     } } 

Screen shot

Label rendered on image

like image 83
Andrew Thompson Avatar answered Sep 23 '22 15:09

Andrew Thompson