Search code examples
javaswingcanvasjpaneljavax.imageio

How can I save the lines painted in a JPanel?


I was at first looking for a library to make a "mousewritten" or "handwritten" signature for java. I did not found any so I'm just trying to let the user draw in a canvas on a JPanel and then he can choose to save it, repaint it or cancel the signature. The problem I have is when I'm trying to save the drawed stuff in the canvas I get an empty .jpeg

My code so far:

import javax.swing.*;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.colorchooser.*;
import javax.swing.event.*;

import java.awt.geom.Line2D;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.logging.Logger;

import javax.imageio.ImageIO;


public class AES_Encryption extends JFrame implements ActionListener{



public BufferedImage image = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
//JPanel canvas = new JPanel();

    JPanel buttonPanel = new JPanel();
    Point lastPos = null;
    Point startPos = null;
    Point finishPos = null;
    Graphics g;
    JButton save = new JButton("Save");
    JButton cancel = new JButton("Cancel");
    JButton clear = new JButton("Clear");
    JPanel canvas = new JPanel();
    int changer = 1;
    String path="";

    public AES_Encryption () {


        setLocation(100,100);
        setSize(600,500);
        setTitle("ENCODE SECTION");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        canvas.setBackground(Color.WHITE);

        clear.addActionListener(this);
        clear.setActionCommand("clear");

        save.addActionListener(this);
        save.setActionCommand("Save");


        cancel.addActionListener(this);
        cancel.setActionCommand("Cancel");


        //add buttons here

        buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS));
        buttonPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
        buttonPanel.add(Box.createHorizontalGlue());
        buttonPanel.add(save);
        buttonPanel.add(Box.createRigidArea(new Dimension(10, 0)));
        buttonPanel.add(clear);
        buttonPanel.add(Box.createRigidArea(new Dimension(10, 0)));
        buttonPanel.add(cancel);

        //set the look
        getContentPane().add(canvas, BorderLayout.CENTER);
        getContentPane().add(buttonPanel, BorderLayout.SOUTH);
        setVisible(true);

        g = canvas.getGraphics();
        g.setColor(Color.BLACK);

        canvas.addMouseMotionListener(new MouseMotionListener () {                      
            public void mouseDragged (MouseEvent m) {
                Point p = m.getPoint() ;
                if (changer==1){
                g.drawLine(lastPos.x, lastPos.y, p.x, p.y) ;
                }           
                lastPos = p ;

            }   
            public void mouseMoved (MouseEvent m) {}
        });

        canvas.addMouseListener(new MouseListener () {
            public void mouseClicked(MouseEvent e) {startPos = e.getPoint();}
            public void mousePressed(MouseEvent e) {lastPos = e.getPoint();}
            public void mouseReleased(MouseEvent e) {
            lastPos = null; 
            finishPos = e.getPoint(); 
            startPos = null;}
            public void mouseEntered(MouseEvent e) {}
            public void mouseExited(MouseEvent e) {}
            });


    }



    public void actionPerformed(ActionEvent e) {
        if("clear".equals(e.getActionCommand())) {
            repaint();
        }
        if("Save".equals(e.getActionCommand())) {
            captureCanvasImage myCanvas = new captureCanvasImage();
            myCanvas.capture();
        }
        if("Cancel".equals(e.getActionCommand())) {
            dispose();
        }}


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

            }


    /*
    @Override
    public void invalidate() {     
    super.invalidate(); 

    this.paint(this.getGraphics()); 
    }
*/

    public static void main (String [] args) {
        AES_Encryption p = new AES_Encryption();
        p.setVisible(true);
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        p.setLocation(dim.width/2-p.getSize().width/2, dim.height/2-p.getSize().height/2);
    }
}

Solution

  • When you create the coordinates of the line, save them in a list.

    
                List<Point> points = new ArrayList<>(); // instance field.
    
                canvas.addMouseMotionListener(new MouseMotionListener () {                      
                public void mouseDragged (MouseEvent m) {
                    Point p = m.getPoint() ;
                    if (changer==1){
                    g.drawLine(lastPos.x, lastPos.y, p.x, p.y) ;
                    points.add(lastPos);// add it here.
                    }           
                    lastPos = p ;
    
                }   
                public void mouseMoved (MouseEvent m) {}
            });
    
    

    This was an example. You need to determine where to place the points.add() code. Check out the painting examples here

    EDITED:

    Here is an example of how to draw in a window. Do not be using graphics context outside of a painting environment like paint or paintComponent (exceptions to this are buffered images,etc which do not paint within the EDT).

    
        import java.awt.BasicStroke;
        import java.awt.Color;
        import java.awt.Dimension;
        import java.awt.Graphics;
        import java.awt.Graphics2D;
        import java.awt.Point;
        import java.awt.RenderingHints;
        import java.util.List;
        import java.util.Random;
        import java.util.stream.Collectors;
        import java.util.stream.IntStream;
    
        import javax.swing.JFrame;
        import javax.swing.JPanel;
        import javax.swing.SwingUtilities;
    
        public class ExampleDrawDemo extends JPanel {
    
           int        WIDTH  = 600;
           int        HEIGHT = 500;
           JFrame     frame  = new JFrame();
           List<Line> lines;
    
           public static void main(String[] args) {
              SwingUtilities.invokeLater(() -> new ExampleDrawDemo().start());
           }
           public void start() {
              Random r = new Random();
              Color[] color = {
                    Color.RED, Color.BLUE, Color.GREEN, Color.MAGENTA, Color.ORANGE,
                    Color.CYAN
              };
    
              // generate some lines.
              lines = IntStream.range(0, 100).mapToObj(
                    i -> new Line(r, color[r.nextInt(color.length)])).collect(
                          Collectors.toList());
    
              setPreferredSize(new Dimension(600, 500));
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              frame.add(this);
              frame.pack();
              frame.setLocationRelativeTo(null);
              frame.setVisible(true);
           }
    
           public void paintComponent(Graphics g) {
              super.paintComponent(g);
              Graphics2D g2d = (Graphics2D) g.create();
              // smooth lines
              g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                       RenderingHints.VALUE_ANTIALIAS_ON);
              // line thickness
              g2d.setStroke(new BasicStroke(2));
    
              for (Line line : lines) {
                 g2d.setColor(line.color);
                 g2d.drawLine(line.start.x, line.start.y, line.end.x, line.end.y);
              }
              g2d.dispose();
           }
    
           class Line {
              Point start;
              Point end;
              Color color;
    
              public Line(Random r, Color color) {
                 this.color = color;
                 start = new Point(r.nextInt(WIDTH), r.nextInt(HEIGHT));
                 end = new Point(r.nextInt(WIDTH), r.nextInt(HEIGHT));
              }
           }
        }