0

I'm looking to take a screenshot of what is currently happening in my program for use in the background of a pause menu. I've found the code:

BufferedImage x = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));

which does take a screenshot and works well, the thing is it also includes my windows border which definitely shouldn't be included. I've snooped around the web and I haven't seen a function to take a screen shot JUST of whats inside the border. Alternatively, finding the thickness of the border on the top, bottom, and sides would also work but I haven't found any info on that.

Whats the best way to do this?

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Nat
  • 890
  • 3
  • 11
  • 23

2 Answers2

2

Instead of capturing the frame bounds, you should try capturing the contents instead, for example...

JRootPane rootPane = frame.getRootPane();
Rectangle bounds = new Rectangle(rootPane.getSize());
bounds.setLocation(rootPane.getLocationOnScreen());
BufferedImage contentsImage = bot.createScreenCapture(bounds);

This will capture the menu bar as well, if you only want the physical contents, you should use frame.getContentPane() instead of frame.getRootPane()

For example...

Original frame
Original

Capture results (full frame/root pane)
Capture

import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class ScreenShot {

    public static void main(String[] args) {
        new ScreenShot();
    }

    public ScreenShot() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                final JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());

                JButton capture = new JButton("Snap shot");
                capture.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        try {
                            Robot bot = new Robot();
                            BufferedImage frameImage = bot.createScreenCapture(frame.getBounds());
                            JRootPane rootPane = frame.getRootPane();
                            Rectangle bounds = new Rectangle(rootPane.getSize());
                            bounds.setLocation(rootPane.getLocationOnScreen());
                            BufferedImage contentsImage = bot.createScreenCapture(bounds);

                            JPanel panel = new JPanel(new GridLayout(1, 2));
                            panel.add(new JLabel(new ImageIcon(frameImage)));
                            panel.add(new JLabel(new ImageIcon(contentsImage)));

                            JOptionPane.showMessageDialog(frame, panel);

                        } catch (AWTException ex) {
                            ex.printStackTrace();
                        }
                    }
                });

                frame.add(capture, BorderLayout.SOUTH);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {

            setLayout(new BorderLayout());

            try {
                BufferedImage img = ImageIO.read(new File("C:\\Users\\shane\\Dropbox\\Ponies\\sillydash-small.png"));
                JLabel label = new JLabel(new ImageIcon(img));
                add(label);
            } catch (IOException ex) {
                ex.printStackTrace();
            }

        }

    }

}

Oddly enough, you can use this approach for just about any component you want...

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Worked perfectly! I forgot about using rootPane for sizes and positions, I knew there must be some object that contains everything and covers everything between the borders, just couldn't remember which! Thanks! – Nat Oct 15 '14 at 23:28
0

You can try making your own function:

public static final void makeScreenshot(JFrame f) {
    Rectangle rec = f.getBounds();
    BufferedImage bufferedImage = new BufferedImage(rec.width, rec.height,
            BufferedImage.TYPE_INT_ARGB);
    f.paint(bufferedImage.getGraphics());

    try {
        // Create temp file
        File temp = File.createTempFile("screenshot", ".png");

        ImageIO.write(bufferedImage, "png", temp);

        // Delete temp file on exit
        temp.deleteOnExit();
    } catch (IOException ioe) {
        LOGGER.debug(ioe.toString());
    } 
} 

This does not include the frame itself or titlebar, so it should suit your needs.

edit Edited to include saving the shot.

Tetramputechture
  • 2,911
  • 2
  • 33
  • 48
  • `JFrame#getBounds` does include the frame board, it represents the outer edge of the window, everything else is displayed within it...Depending on the look and feel and other settings will depend on what `paint` will do, but you should be using `print` or `printAll` over `paint` as it's more efficient and disables double buffering – MadProgrammer Oct 15 '14 at 23:26
  • Oh, apparently, `paint` doesn't paint the border, there you go, but I would suggest the other corrections would be helpful (ie `print` instead of `paint`) ;) – MadProgrammer Oct 15 '14 at 23:29