私はそれを覆っている画像のあるフレームを持っています.そして、誰かが画像内の別のオブジェクトをクリックするたびに、それがボタンとして機能し、何かをすることを望みます.
問題は、それらのオブジェクトが単純な形状ではないことです。そのため、これらのオブジェクトの形状で自分の目に見えないボタンを描くことを考えていました。
それは可能ですか?または、そのようなことを達成するためのより良い方法は何でしょうか?
-ありがとうございました
私はそれを覆っている画像のあるフレームを持っています.そして、誰かが画像内の別のオブジェクトをクリックするたびに、それがボタンとして機能し、何かをすることを望みます.
問題は、それらのオブジェクトが単純な形状ではないことです。そのため、これらのオブジェクトの形状で自分の目に見えないボタンを描くことを考えていました。
それは可能ですか?または、そのようなことを達成するためのより良い方法は何でしょうか?
-ありがとうございました
コンセプト: 円形および多角形のディスパッチ エリアを備えた目に見えないボタン
まず、非表示のボタンを定義するクラスが必要であり、javax.swing.AbstractButton
リスナーを追加できる完全に機能するボタンになるように拡張します。
public abstract class InvisibleButton extends AbstractButton {
public abstract boolean contains(Point point);
@Override
public boolean isVisible() {
return false;
}
}
もちろん、そのクラスの実装が必要になります。2 つの例を次に示します。1 つは複雑な形状に多角形を使用し、もう 1 つは円を使用しています。
public class PolygonalButton extends InvisibleButton {
private Polygon area = null;
public PolygonalButton(Polygon area) {
this.area = area;
}
@Override
public boolean contains(Point point) {
return area.contains(point);
}
}
public class CircularButton extends InvisibleButton {
private int x;
private int y;
private double radius;
public CircularButton(int x, int y, double radius) {
this.x = x;
this.y = y;
this.radius = radius;
}
@Override
public boolean contains(Point point) {
double dx = x - point.x;
double dy = y - point.y;
return Math.sqrt(dx * dx + dy * dy) <= radius;
}
}
最後に、これらすべてのボタンを処理するコンテナーを実装する必要がありますが、フレームではなくパネルを使用する必要があります。個々のリスナーをフックするのではなく、フレームのイベント プロセッサをオーバーライドして必要なボタンに渡すことができます。
public class InvisibleButtonImagePanel extends JPanel {
private BufferedImage image = null;
private List<InvisibleButton> buttons = new ArrayList<>();
public InvisibleButtonImagePanel(BufferedImage image) {
this.image = image;
}
public void add(InvisibleButton button) {
buttons.add(button);
}
public void remove(InvisibleButton button) {
buttons.remove(button);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(image.getWidth(), image.getHeight());
}
@Override
public void processKeyEvent(KeyEvent event) {
for (InvisibleButton button : buttons) {
if (button.isFocusOwner()) {
button.dispatchEvent(event);
}
}
super.processKeyEvent(event);
}
@Override
public void processMouseEvent(MouseEvent event) {
for (InvisibleButton button : buttons) {
if (button.contains(event.getPoint())) {
button.dispatchEvent(event);
}
}
super.processMouseEvent(event);
}
@Override
protected void paintComponent(Graphics g) {
g.drawImage(image, 0, 0, null);
super.paintComponent(g);
}
}
おそらく、パネルの名前をかさばらない名前に変更したり、独自の高度な画像コードを実装したりすることになるでしょうが、それがその背後にある基本的な考え方です。
そして、誰かが画像内の別のオブジェクトをクリックするたびに、それがボタンとして機能し、何かをすることを望んでいます。
オブジェクトの ArrayList を作成できShape
ます。次に、画像を含むコンポーネントに MouseListener を追加します。mousePressed イベントが生成されるたびに、ArrayList をループし、コンポーネントの contains(...) メソッドを使用して、ユーザーが Shapes 座標をクリックしたかどうかを判断します。
シェイプで遊ぶ をご覧ください。このコードは差し迫った問題の解決には役立ちませんが、Shapes
定義できる の型についてのアイデアを提供します。
次のようなリージョンのインターフェースを定義します。
//represents any clickable area.
public interface IButton{
boolean contains(int x, int y);
}
次に、円形の領域をクリック可能にする場合は、x、y 座標が位置から一定の距離内にあるかどうかをチェックするクラスを定義します。
public class CircleButton implements IButton{
Point center;
double radius;
public CircleButton(int x, int y, double radius){
this.center = new Point(x,y);
this.radius = radius;
}
//check if x,y coords are within a radius
//from the center of this circle button
public boolean contains(int x, int y){
double dx = x-center.x;
double dy = y-center.y;
return (Math.sqrt(dx*dx+dy*dy) <= radius);
}
}
IButton のリストを作成します。これらを反復処理して、ユーザーが非表示のボタンの 1 つをクリックしたかどうかを確認します。
List<IButton> buttons = new List<IButton>();
buttons.add(new CircleButton(100,100,200);
次に、誰かがフレームをクリックするたびに、そのマウス クリックの位置を使用して、目に見えないボタンを反復処理します。
public void mouseReleased(MouseEvent e){
for(IButton b : buttons){
if(b.contains(evt.getX(),e.getY()){
//do something depending on what button was clicked.
}
}
}
このような目に見えない長方形のボタンや、不規則な多角形の形状を定義する方法を簡単に確認できます。contains
メソッドを正しく実装する必要があるだけです。