During my last project at the university, I made a whiteboard program and had the same problem. For each shape that the user drew on the board, I created a JComponent, which was great when they drew rectangles, but harder with the free form tool.
The way I fixed it, in the end, was to completely destroy JComponents. I had a JPanel in which a vector (I think) of custom Shape objects was stored. Each object had its own coordinates and line thickness, etc. When the user clicked on the board, the mouse listener on the JPanel fired and went through each Shape, calling the a (int x, int y) method on each of them (x and y are the coordinates of the event). Since the shapes were added to the vector when they were drawn, I knew that the latter, to return true, was the topmost shape.
This is what I used for the straight line method contains. Math may be a bit, but it worked for me.
public boolean contains(int x, int y) { // Check if line is a point if(posX == endX && posY == endY){ if(Math.abs(posY - y) <= lineThickness / 2 && Math.abs(posX - x) <= lineThickness / 2) return true; else return false; } int x1, x2, y1, y2; if(posX < endX){ x1 = posX; y1 = posY; x2 = endX; y2 = endY; } else{ x1 = endX; y1 = endY; x2 = posX; y2 = posY; } /**** USING MATRIX TRANSFORMATIONS ****/ double r_numerator = (x-x1)*(x2-x1) + (y-y1)*(y2-y1); double r_denomenator = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1); double r = r_numerator / r_denomenator; // s is the position of the perpendicular projection of the point along // the line: s < 0 = point is left of the line; s > 0 = point is right of // the line; s = 0 = the point is along the line double s = ((y1-y)*(x2-x1)-(x1-x)*(y2-y1) ) / r_denomenator; double distance = Math.abs(s)*Math.sqrt(r_denomenator); // Point is along the length of the line if ( (r >= 0) && (r <= 1) ) { if(Math.abs(distance) <= lineThickness / 2){ return true; } else return false; } // else point is at one end of the line else{ double dist1 = (x-x1)*(x-x1) + (y-y1)*(y-y1); // distance to start of line double dist2 = (x-x2)*(x-x2) + (y-y2)*(y-y2); // distance to end of line if (dist1 < dist2){ distance = Math.sqrt(dist1); } else{ distance = Math.sqrt(dist2); } if(distance <= lineThickness / 2){ return true; } else return false; } /**** END USING MATRIX TRANSFORMATIONS****/ }
posX and posY are the coordinates of the beginning of the line and endX, and endY is yep, the end of the line. This is returned if the click is within lineThickness / 2 of the center of the line, otherwise you need to click in the very middle of the line.
Drawing shapes is a case of passing each Shape to a JPanel Graphics object and drawing with it.
source share