Naveen Niraula Naveen Niraula - 4 months ago 16
Java Question

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.

Answer

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) {
    }
}
Comments