Search code examples
javaswinglinepaintcomponent

how to fill spaces between lines?


I am trying to make a simple paint program. I am trying to make a tool like pencil which allows free drawing. So far my codes are:

NPaintMain

public class NPaintMain {
    public static void main(String[] args) {
        new NPaintWindow();
    }
}

NPaintWindow

public class NPaintWindow {
    private JFrame windowFrame;
    private String windowTitle;
    private NPaintCanvas canvas;
    private Container easel;    
    public NPaintWindow() {
        windowTitle = "NPaint - a simple paint program.";
        windowFrame = new JFrame(windowTitle);
        windowFrame.setDefaultCloseOperation(windowFrame.EXIT_ON_CLOSE);
        windowFrame.setSize(500, 500);
        windowFrame.setLocationRelativeTo(null);
        canvas = new NPaintCanvas();
        easel = windowFrame.getContentPane();
        easel.add(canvas);   
        windowFrame.setVisible(true);
    }
}

NPaintCanvas

public class NPaintCanvas extends JPanel {
    double x, y, px, py;
    ArrayList<Line2D> l;
    public NPaintCanvas() {
        new NPaintMouseEvents(this);
        x = y = px = py = 0;
        l = new ArrayList<>();
    }
    @Override
    public void paintComponent(Graphics g){
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            for(Line2D ll: l){
                g2d.draw(ll);
            }
            l.add(new Line2D.Double(px, py, x, y));
            g.dispose();
            repaint();
    }
}

NPaintMouseEvents

public class NPaintMouseEvents implements MouseListener,MouseMotionListener {

    NPaintCanvas canvas;

    public NPaintMouseEvents(NPaintCanvas canvas) {
        this.canvas = canvas;
        this.canvas.addMouseMotionListener(this);
        this.canvas.addMouseListener(this);
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        if(canvas.px == 0 && canvas.py == 0){
           canvas.px = e.getX();
            canvas.py = e.getY();
        }
        canvas.x = e.getPoint().x;
        canvas.y = e.getPoint().y;
        canvas.px = canvas.x;
        canvas.py = canvas.y;
    }
}

My main problem here is that while dragging the points are drawn but they have space between them like this. I want joined continuous line. Any help with further tips will be appreciated.


Solution

  • Your problem is that you draw a single point to each mouse dragging move.

    For each drawn line : the x1 and x2 are the same and the y1 and the y2 are the same.
    You should trace a line between two different points. I have updated your code to handle that by introducing two different points : prev and actual points.
    To explain simply, a line is drawn only when the previous and the actual points have values.
    And when a line is drawn, the last actual drawn point becomes the previous point for the next drawn line. In this way, you don't have holes between lines.

    In canvas Class :

    if (previousPoint != null && actualPoint != null) {
         l.add(new Line2D.Double(previousPoint.x, previousPoint.y, actualPoint.x, actualPoint.y));
         previousPoint = new Point(actualPoint.x, actualPoint.y);
    }
    

    If you release your mouse button, the previous and the actual points are set to null.

    In Event class :

     @Override
        public void mouseReleased(MouseEvent e) {
          canvas.mouseReleased();
        }
    

    In canvas Class :

      public void mouseReleased() {
        previousPoint = null;
        actualPoint = null;
      }
    

    In this way, you can draw multiples lines in a independent way if you want.

    Also, i have simplified the code by using Point instances (instead of doubles)which use ints for coordinates but you can use multiple doubles fields, it changes not a lot of things in practice.

    package paint;
    
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Point;
    import java.awt.geom.Line2D;
    
    import java.util.ArrayList;
    
    import javax.swing.JPanel;
    
    public class NPaintCanvas extends JPanel {
        ArrayList<Line2D> l;
        Point actualPoint;
        Point previousPoint;
    
        public NPaintCanvas() {
        new NPaintMouseEvents(this);
          l = new ArrayList<>();
        }
    
    
    
      @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            for (Line2D ll : l) {
                g2d.draw(ll);
            }
            if (previousPoint != null && actualPoint != null) {
                l.add(new Line2D.Double(previousPoint.x, previousPoint.y, actualPoint.x, actualPoint.y));
                previousPoint = new Point(actualPoint.x, actualPoint.y);
            }
            g.dispose();
            repaint();
        }
    
        public void mouseReleased() {
            previousPoint = null;
            actualPoint = null;
        }
    
        public void mousePressed(int x, int y) {
            previousPoint = new Point(x, y);
        }
    }
    

    NPaintMouseEvent

    package paint;
    
    import java.awt.Point;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.awt.event.MouseMotionListener;
    
    public class NPaintMouseEvents implements MouseListener, MouseMotionListener {
    
        NPaintCanvas canvas;
    
        public NPaintMouseEvents(NPaintCanvas canvas) {
          this.canvas = canvas;
          this.canvas.addMouseMotionListener(this);
          this.canvas.addMouseListener(this);
        }
    
        @Override
        public void mouseDragged(MouseEvent e) {
          if (canvas.actualPoint == null) {
             canvas.actualPoint = new Point();
          }
          canvas.actualPoint.x = e.getPoint().x;
          canvas.actualPoint.y = e.getPoint().y;
        }
    
        @Override
        public void mouseMoved(MouseEvent e) {
        }
    
        @Override
        public void mouseClicked(MouseEvent e) {
        }
    
        @Override
        public void mousePressed(MouseEvent e) {
          canvas.mousePressed((int) e.getX(), (int) e.getY());
        }
    
        @Override
        public void mouseReleased(MouseEvent e) {
          canvas.mouseReleased();
        }
    
        @Override
        public void mouseEntered(MouseEvent e) {
        }
    
        @Override
        public void mouseExited(MouseEvent e) {
        }
    }