Java Tips Weblog

Screen Image

Posted by Rob Camick on October 13, 2008

Do you need the ability to create an image of your GUI or a component on your GUI? The easiest way to do this would be to use the Robot class and its createScreenCapture(…) method. This will work whether you have an AWT or Swing application. However, this method is relatively slow as it gets the pixels directly from the screen. There must be a better way.

The better way is to use the Swing JComponent.paint(…) method to draw the Swing component directly onto a BufferedImage. Of course this can only be used on Swing components. This may lead to some confusion because although JFrame, JDialog and JWindow are part of Swing, they actually extend from Component, not JComponent, which means you can’t use the paint(…) method and must use the Robot.

No reason to worry though because the ScreenImage class will take the above into account when creating an image. There are two static methods that can be used to create images:

  • createImage(…) – has several overloaded method signatures that will make sure you are using the most efficient approach no matter what component you are trying to capture.
  • createDestopImage() – is a convenience method which will create an image of the whole desktop.

In general all you need to provide is a reference to the component you want to create an image for. However, if you don’t want the entire component you can specify a region of that component. This is important to understand when creating images for components in a scroll pane. For example, lets say you have a text area with 1,000 lines in scroll pane. You really have 3 ways to create the image:

  • use the JTextArea as the component and all 1,000 lines will be painted, even though they are not visible on the screen
  • use the JTextArea as the component but specify a region so that only a certain number of lines are painted
  • use the JViewport as the component and only the visible lines will be painted.

This class also contains a static writeImage(…) method that allows you to save the created image to a file. The type of file must be supported by the ImageIO write method.

Download the code and check out the API, I’m sure you’ll be using it in no time. I used the following code to create the attached image showing a portion of my desktop:

Rectangle r = new Rectangle(375, 50, 600, 300);
BufferedImage bi = ScreenImage.createImage(r);
ScreenImage.writeImage("Screen-Image.jpg");

Swing components not added to a GUI

Although this class was originally designed to create an image of a component on the screen it can be used to create an image of Swing components not displayed on a GUI. Behind the scenes the ScreenImage class will:

  • set the component size – when the size of a component is 0, the size will be set to the preferred size of the component. Or, you can manually set the size of the component before invoking a createImage(…) method
  • layout the component – components like JPanel, JComboBox, JScrollPane need to be layed out before then can be painted. This class will recursively invoke the doLayout() method on the Containers of the component.

Even with the above features, there is still a possiblity the components image will not be what you expect. For example the image of a table added to a scroll pane will be missing the table header. This is because the header is not added to the scroll pane until the scroll pane has been added to a realized GUI window. That is the window must be packed or made visible. A simple work around for this problem is:

JScrollPane scrollPane = new JScrollPane( table );
scrollPane.setColumnHeaderView( table.getTableHeader() );
ScreenImage.createImage( scrollPane );

If you still encounter problems then the only other suggestion I have is to add the component to a realized frame:

JFrame frame = new JFrame();
frame.setContentPane( someComponent );
frame.pack();
ScreenImage.createImage( someComponent );

Thanks to Maxideon for his comments in this posting which lead to improvements in the creation of images for non displayed components.

Get The Code

ScreenImage.java

4 Responses to “Screen Image”

  1. Anonymous said

    Hi, The code does not seem working for .gif and .bmp.

    I was trying to write a BufferedImage using .createImage method for gif and bmp. GIF says “Unknown writer file suffix gif”.

    BMP, I understand requires some special way of writing. I am not sure why gif would not work as createImage just in turn uses ImageIO write.

  2. camickr said

    Support exists for those two formats in JDK6. I don’t know why they are not supported in earlier versions.

    I have never done it (so don’t ask me how), but I believe you can download support for other writers and instal them into your JDK. You may want to start by reading the ImageWriter API and then search the web for detailed instructions as I don’t think its that simple.

  3. krishna said

    Hi,

    i am facing a problem while saving the panel as a image. i am using bufferedimage to do that .but the problem is it is throwing out of memory exception. my panel size is 1200 width and 64000 height. please help me out

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>