大学での最終年度のプロジェクトでは、ホワイトボードプログラムを実行しましたが、同じ問題が発生しました。ユーザーがボード上に描いた形状ごとに、JComponentを作成しました。これは、長方形を描いているときは問題ありませんでしたが、自由形式の線ツールではさらに困難でした。
最終的に修正した方法は、JComponentsを完全に廃止することでした。カスタムShapeオブジェクトのVector(私は思う)を保持するJPanelがありました。各オブジェクトは、独自の座標や線の太さなどを保持していました。ユーザーがボードをクリックすると、JPanelのマウスリスナーが起動し、各Shapeを通過して、各Shapeでcontains(int x、int y)メソッドを呼び出しました(xとyはイベントの座標です)。シェイプは描画時にベクターに追加されたため、trueを返す最後のシェイプが一番上のシェイプであることがわかりました。
これは私が直線containsメソッドに使用したものです。数学は少し難しいかもしれませんが、それは私にとってはうまくいきました。
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とposYは線の始点の座標を構成し、endXとendYは線の終点です。これは、クリックが線の中心のlineThickness / 2内にある場合にtrueを返しました。そうでない場合は、線の真ん中に沿って右クリックする必要があります。
Shapesの描画は、JPanelのGraphicsオブジェクトを各Shapeに渡し、それを使用して描画を行う場合でした。