Đăng Nguyễn
Đăng Nguyễn

Reputation: 122

Save image from JPanel after draw

I'm newbie in jave, my first project is draw, and save a image from JPanel, my draw is done, but I cant save it after I draw in JPanel :(, So can you help me to fix it when I open the image after draw, It doesn't contain anything :( here my codes:

package image;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;


public class paint extends JFrame{
private Point points[] = new Point[10000];
private Point pointends[] = new Point[10000];
private int pointCount = 0;
private JButton save_btn;
public paint()
{
    panel paint2 = new panel();
    add(paint2,BorderLayout.CENTER);
}
private class panel extends JPanel
{   
    private paint my_paint;
    public panel()
    {   
        setBackground(Color.WHITE);
        save_btn = new JButton();
        save_btn.setText("123");
        this.add(save_btn);
        ButtonHandler handler1 = new ButtonHandler();
        save_btn.addActionListener(handler1);
        MouseHandler handler = new MouseHandler();
        this.addMouseMotionListener(handler);

        this.addMouseListener(handler);
    }
    private class ButtonHandler implements ActionListener
    {

        @Override
        public void actionPerformed(ActionEvent arg0) {
            // TODO Auto-generated method stub
            savefile();
        }

    }
    @Override
    protected void paintComponent(Graphics g) 
    {
        // TODO Auto-generated method stub
        super.paintComponent(g);
        for(int i = 0;i <pointCount;i++)
        {   
            g.setColor(Color.RED);
            g.drawLine(points[i].x, points[i].y, pointends[i].x, pointends[i].y);
        }           
    }



private class MouseHandler extends MouseAdapter
{  
    @Override
    public void mouseDragged(MouseEvent e) 
    {
        // TODO Auto-generated method stub
            pointends[ pointCount-1] = e.getPoint();
            repaint();


    }
    @Override
    public void mousePressed(MouseEvent e) {
        // TODO Auto-generated method stub
        super.mousePressed(e);
        if(pointCount < points.length)
        {
            points[ pointCount ] = e.getPoint();
            pointends[ pointCount ] = e.getPoint();
            pointCount++; 
            repaint();
        }
    }
    @Override
    public void mouseReleased(MouseEvent e) {
        // TODO Auto-generated method stub
        super.mouseReleased(e);
        /*pointends[pointCount]=e.getPoint();
        repaint();
        pointCount++;
    */
    }

    }

}
public void savefile()
{
    BufferedImage image2 = new BufferedImage(panel.WIDTH, panel.HEIGHT,     BufferedImage.TYPE_INT_RGB);
    JFileChooser jFile = new JFileChooser();
    jFile.showSaveDialog(null);
    Path pth = jFile.getSelectedFile().toPath();
    JOptionPane.showMessageDialog(null, pth.toString());
    Graphics2D graphics2D = image2.createGraphics();
    try {
        ImageIO.write(image2, "", new File(pth.toString()));
    } catch (IOException ox) {
        // TODO: handle exception
        ox.printStackTrace();

}
}
}

Upvotes: 6

Views: 32302

Answers (4)

刘远圳
刘远圳

Reputation: 594

private void saveImage(){
    BufferedImage imagebuf=null;
    try {
        imagebuf = new Robot().createScreenCapture(panel.bounds());
    } catch (AWTException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }  
     Graphics2D graphics2D = imagebuf.createGraphics();
     panel.paint(graphics2D);
     try {
        ImageIO.write(imagebuf,"jpeg", new File("save1.jpeg"));
    } catch (Exception e) {
        // TODO Auto-generated catch block
        System.out.println("error");
    }
}

result example of snippet code

Upvotes: 6

Sage
Sage

Reputation: 15408

There is a nice approach:

BufferedImage image = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics g = image.getGraphics();
component.paint(g);
 try {
        ImageIO.write(image, "png", new File(filename));
    } catch (IOException ex) {
        Logger.getLogger(CustomApp.class.getName()).log(Level.SEVERE, null, ex);
   }

All what it does: It creates an image with visible component's size and ARGB type for transparency support. Then it get the graphics and pass that to the component we want to have snapshot of. It paints that component's child component including anything drawn on it.

Update: You can use component.print(Graphics g) too:

Dimension componentSize = component.getPreferredSize();
component.setSize(componentSize); // need to make sure that both sizes are equal
BufferedImage image = new BufferedImage(comonent.getWidth(), component.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = image.createGraphics();
g.fillRect(0, 0, image.getWidth(), image.getHeight());
component.print(g);

But this function will draw only the rendered graphics of the component but not the child components. I have tested it.


Edit:

  1. Your paint extends JFrame class can have a nice name, e.g., PaintFrame extends JFrame. Class name should not have a name of a function, paint is a verb, it is a function.
  2. panel extends JPanel : why should we go down choosing a class name with first letter of lower case? We can give our component name to reflect what we are doing with it: like, we are drawing so what about MyCanvas extends JPanel
  3. Inside the panel your first statement private paint my_paint; : what is it doing here unnecessarily ?
  4. your saveFile() function belongs to the JFrame and you have created your panel (on which you are drawing) local to the frame constructor. How should the saveFile() function have access to it? Declare your painting Panel in the JFrame class context as public or private.
  5. I have written in a meaningful way to read the sizes of the component using getWidth() and getHeight() But you are writing:

         BufferedImage image2 = new BufferedImage(panel.WIDTH, panel.HEIGHT, ...);
    

And again i have completely written the code how to save the image as a png using ImageIO.write(image, "png", "myFile.png") function. Please read the answers carefully.

Following resources might be helpful:

  1. A closer look at painting mechanism.
  2. Writing and saving images

Upvotes: 6

lol
lol

Reputation: 3390

Create BufferedImage to store your painting. When you paint, paint on BufferedImage.

When you need to display paint on JPanel, draw BufferedImage on JPanel.

This way, you can load / save painting to file.

Something like this:

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class Paint extends JPanel{
    private BufferedImage paintImage = new BufferedImage(500, 400, BufferedImage.TYPE_3BYTE_BGR);

    @Override
    protected void paintComponent(Graphics g){
        super.paintComponent(g);
        g.drawImage(paintImage, 0, 0, null);
    }

    // draw painting
    public void updatePaint(){
        Graphics g = paintImage.createGraphics();

        // draw on paintImage using Graphics

        g.dispose();
        // repaint panel with new modified paint
        repaint();
    }

    public void save() throws IOException{
        ImageIO.write(paintImage, "PNG", new File("filename.png"));
    }

    public void load() throws IOException {
        paintImage = ImageIO.read(new File("filename.png"));
        // update panel with new paint image
        repaint();
    }
}

Upvotes: 14

camickr
camickr

Reputation: 324078

Screen Image allows you to save an image of any component.

Upvotes: 0

Related Questions