0

I am working on a white board project and I encountered a problem when implementing the Save function.

Here is how I implement the draw function

Graphics2D g2d = (Graphics2D) frm.getGraphics();
g2d.setColor(Current_Color);
Line2D p2d = new Line2D.Double(StartPoint.getX(),StartPoint.getY(), e.getX() 
     + Xoffset, e.getY() + Yoffset);
g2d.setStroke(new BasicStroke(Integer.parseInt(choice_size.getSelectedItem())));
g2d.draw(p2d);

I am using JFileChooser for the file dialog

            int returnVal = saveFileChooser.showSaveDialog(frm);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                File currentDir = saveFileChooser.getCurrentDirectory();
                String fileName = saveFileChooser.getSelectedFile()
                        .getName();
                String savePath = currentDir + "\\" + fileName + ".jpg";

                try {
                    ImageIO.write(<image>,<suffix>,<file>);
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }

There is no method like Frame.getImage() for JFrame, I am wondering how can I save what I draw on the JFrame as an image ?

mKorbel
  • 109,525
  • 20
  • 134
  • 319
PinkiePie-Z
  • 525
  • 1
  • 6
  • 28

1 Answers1

4

You need to paint the frame's content to a BufferedImage first. Try something like...

Container content = frm.getContentPane();
BufferedImage img = new BufferedImage(container.getWidth(), container.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = img.createGraphics();

content.printAll(g2d);

g2d.dispose();

Once you have that, you can use the ImageIO.write method, passing the img to it.

UPDATE

So, I did a really quick test...

I started out with this background image...

background

Which I loaded into my frame and laid a JLabel ontop

Frame

And then saved to a file...

Output

All of which worked fine.

This is the code that I used.

public class TestSaveFrame extends JFrame {

    public static void main(String[] args) {

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

    public TestSaveFrame() {

        setTitle("Save me");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        BackgroundPane pane = new BackgroundPane();
        pane.setLayout(new GridBagLayout());

        JLabel label = new JLabel("I'm sitting on top");
        label.setFont(label.getFont().deriveFont(Font.BOLD, 24f));
        label.setForeground(Color.WHITE);

        pane.add(label);

        add(pane);

        pack();
        setLocationRelativeTo(null);
        setVisible(true);

        pane.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {

                if (e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) {
                    Container content = getContentPane();
                    BufferedImage img = new BufferedImage(content.getWidth(), content.getHeight(), BufferedImage.TYPE_INT_RGB);
                    Graphics2D g2d = img.createGraphics();
                    content.printAll(g2d);
                    g2d.dispose();

                    try {
                        ImageIO.write(img, "png", new File("C:/PrintMe.png"));
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
            }
        });

    }

    public class BackgroundPane extends JPanel {

        private Image background = null;

        public BackgroundPane() {
            try {
                background = ImageIO.read(getClass().getResource("/MT015.jpg"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return background == null ? new Dimension(200, 200) : new Dimension(background.getWidth(this), background.getHeight(this));
        }

        @Override
        protected void paintComponent(Graphics g) {

            super.paintComponent(g);
            if (background != null) {
                int x = (getWidth() - background.getWidth(this)) / 2;
                int y = (getHeight() - background.getHeight(this)) / 2;

                g.drawImage(background, x, y, this);
            }
        }
    }
}

Without an example of the work flow, it's going to be tough to work out where you're going wrong.

I should note that I use printAll over paint because I've had issues with doing this using paint recently (throwing exceptions and the like)

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • yeah, I've tried before, but if I add that inside the JFileChooser part, the picture I drew before will disappear, that is to say, it can not get the current content on the JFrame. – PinkiePie-Z Sep 25 '12 at 02:08
  • I've added an example to my answer for you to look over – MadProgrammer Sep 25 '12 at 02:47
  • It sounds like the content is be cleared before the JFileChooser is been displayed? Is this part of the application? Does the content remain after the dialog is closed??? If this is the case, you may need to grab a copy the content (via the `BufferedImage`) and pass it to the save method instead – MadProgrammer Sep 25 '12 at 02:49
  • `Container cont = frm.getContentPane(); BufferedImage image = new BufferedImage(cont.getWidth(),cont.getHeight(),BufferedImage.TYPE_INT_RGB); ImageIO.write(image, "png", new File(savePath));` – PinkiePie-Z Sep 26 '12 at 00:30
  • Okay, first comment is, is the frame visible on the screen and has it been laid out??? – MadProgrammer Sep 26 '12 at 00:42
  • it is visible and is used to perform `frm.getGraphics()`, but the draw part and the save part is separated, so should i set the `BufferedImage image` to a global variant and use this to print the picture ? – PinkiePie-Z Sep 26 '12 at 01:15
  • In the example you posted in the comments, you're not painting the frame to the `BufferedImage`. `Graphics2D g2d image.createGraphics(); frm.printAll(g2d); g2d.dispose(); // save image...` – MadProgrammer Sep 26 '12 at 01:21
  • does it mean that if I want to open/save an image, 1. create a JFrame; 2. get the ContentPane of the frame; 3. create a BufferedImage on the ContentPane; 4. create a Graphics for the BufferedImage; 5. draw on the ContentPane. Then, next time when I need to save, I can just save the image, is that right ? – PinkiePie-Z Sep 26 '12 at 02:23
  • No. Graphics don't work that way. Every time you want to save the image, you must read off the frm (by painting using the buffered image's graphics context)... – MadProgrammer Sep 26 '12 at 02:28
  • I just can't get it right...may I have your E-mail address for further discussion ? – PinkiePie-Z Sep 26 '12 at 04:45
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/17161/discussion-between-madprogrammer-and-z-pyyyy) – MadProgrammer Sep 26 '12 at 04:54