7

I am trying to render a JFrame to an image without ever displaying the JFrame itself (similar to what this question is asking). I have tried using this piece of code:

private 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());
    return image;
}

However, this only works when the JFrame's setVisible(true) is set. This will cause the image to be displayed on the screen which is not something I want. I have also tried to create something like so:

public class MyFrame extends JFrame
{
    private BufferedImage bi;

    public MyFrame(String name, BufferedImage bi)
    { 
         this.bi = bi;
         super(name);
    }

    @Override
    public void paint(Graphics g)
    {
         g.drawImage(this.bufferedImage, 0, 0, null);
    }
}

This however displays black images (like the code above). I am pretty sure that what I am after is possible, the problem is that I can't really find how. My experience with custom Swing components is pretty limited, so any information will be appreciated.

Thanks.

Community
  • 1
  • 1
npinti
  • 51,780
  • 5
  • 72
  • 96
  • 1
    [this could be works without caused issues with black ...](http://tips4java.wordpress.com/2008/10/13/screen-image/), no idea without an SSCCE – mKorbel Sep 18 '12 at 13:07
  • 1
    @mKorbel: The code I have posted is exactly what I am trying to do. I have tried to use that class, but it also rendered black images. – npinti Sep 18 '12 at 13:09
  • 1
    JComponents, then JFrames RootPane can returns its coordinates or Graphics in the cases, for already visible container, after call pack(), ContentPane isn't proper container for Graphics(2d), use JComponents / JPanel by override get/setPreferredSize or use scalled instance for Image (not sure about proper methods about additional methods, Image, Graphics are not my cup of Java) – mKorbel Sep 18 '12 at 13:20

2 Answers2

12

Here is a snippet that should do the trick:

Component c; // the component you would like to print to a BufferedImage
JFrame frame = new JFrame();
frame.setBackground(Color.WHITE);
frame.setUndecorated(true);
frame.getContentPane().add(c);
frame.pack();
BufferedImage bi = new BufferedImage(c.getWidth(), c.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = bi.createGraphics();
c.print(graphics);
graphics.dispose();
frame.dispose();
Guillaume Polet
  • 47,259
  • 4
  • 83
  • 117
  • 1
    @DavidKroukamp Thanks. I just looked again, createGraphics returns a Graphics2D, so no need to cast ;-) Cheers. – Guillaume Polet Sep 18 '12 at 15:24
  • Thanks a lot this worked for me. I just needed to pass `jFrame.getContentPane()` together with what you suggested. One more thing, using `ARGB` produces a slightly pinkish image. I used the usual `RGB` to fix that. – npinti Sep 18 '12 at 15:38
  • @npinti it depends of what you are trying to achieve. If you want to also handle transparency, you will need ARGB, if not, RGB is your friend indeed ;) – Guillaume Polet Sep 18 '12 at 15:46
  • @GuillaumePolet: Yes indeed. Thankfully it is just a plain image, no need for transparency and extra stuff. – npinti Sep 19 '12 at 05:10
  • Doesn't work (works weird). Apart from drawing on `bi` which works, it also draws on top of the current GUI. – Mark Jeronimus Oct 08 '14 at 12:23
  • @MarkJeronimus It does work. You should probably post a question on SO with your complete example so that we can find out what's not working. – Guillaume Polet Oct 08 '14 at 20:55
4

This method might do the trick:

public BufferedImage getImage(Component c) {
    BufferedImage bi = null;
    try {
        bi = new BufferedImage(c.getWidth(),c.getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d =bi.createGraphics();
        c.print(g2d);
        g2d.dispose();
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
    return bi;
}

you'd then do something like:

JFrame frame=...;
...
BufferedImage bImg=new ClassName().getImage(frame);
//bImg is now a screen shot of your frame
David Kroukamp
  • 36,155
  • 13
  • 81
  • 138