Endrew
Endrew

Reputation: 177

How to add mouse listener to lines drawn with Graphics.drawLine()

As the title says, I want to be able to right-click lines I've drawn on Jpanel. Since those lines aren't Components I can't simply add MouseListener to them. Currently I'm drawing lines on my Jpanel with the following code:

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;
    for (UserDrawnLine line : userDrawnLines) {
        g.setColor(new Color(line.colorRValue,line.colorGValue, line.colorBValue));
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setStroke(new BasicStroke(line.thickness));
        g.drawLine(line.startPointX, line.startPointY, line.endPointX, line.endPointY);
    }
}

This is my UserDrawnLine class:

public class UserDrawnLine {
    public int startPointX;
    public int startPointY;
    public int endPointX;
    public int endPointY;
    public int colorRValue;
    public int colorGValue;
    public int colorBValue;
    public float thickness;



    public UserDrawnLine(int startPointX, int startPointY, int endPointX, int endPointY, int colorRValue,int colorGValue,int colorBValue, float thickness) {
        this.startPointX = startPointX;
        this.startPointY = startPointY;
        this.endPointX = endPointX;
        this.endPointY = endPointY;
        this.colorRValue=colorRValue;
        this.colorBValue=colorBValue;
        this.colorGValue=colorGValue;
        this.thickness=thickness;
    }
}

I've been thinking about storing points through which the line goes and then reacting accordingly when user clicks on Jpanel on one of those points. However this doesn't seem like the best solution. Any better ones?

Upvotes: 0

Views: 292

Answers (1)

copeg
copeg

Reputation: 8348

Create a Collection Lines and, using the Point provided from the MouseEvent in the MouseListener, iterate over the Collection and check if the point is on each Line. You may have to roll your own Line class and implement a contains method (note that the Line2D cannot be used as it's contains method always returns false).

To determine if a Point P is on the line:

distance(P, A) + distance(P, B) = distance(A,B)

Where A and B are the line endpoints, and P is the test point. One can use an error term to allow for points that are near but not exactly on the Line (for instance, when using wider strokes to render, you might wish to increase this error term). Assuming your class has endpoints a and b:

public boolean contains(Point p, double error){
    double dist = Math.sqrt(Math.pow(p.x - a.x, 2) + Math.pow(p.y - a.y, 2)) + 
            Math.sqrt(Math.pow(p.x - b.x, 2) + Math.pow(p.y - b.y, 2));
    return Math.abs(dist - this.distance) <= error;
}

Upvotes: 1

Related Questions