初めに
前回の記事ではマスコットの表示と反転までを作成しました。
今回はマウスで動かせるように処理を追加していこうと思います。
JavaFXで行っていた時と異なり、マウスイベントについて実装を変える必要があったので
そのあたりが中心になります。
MouseListenerの関数型インターフェース化
JavaFXで作成していたころはFxmlにイベントを定義していましたが、
今回からはSwingを使用しているため、同じようにはいきません。
JFrameのマウスイベントを設定するためにはMouseListenerインターフェースを
実装する必要があります。
このインターフェースにはマウス操作の必要なメソッドがずらっと定義されています。
これは関数型インターフェースではないため、ラムダで記述できないのです。
マウスイベントごとに実装クラスを作成したり、何かしらの条件分岐を作れば
実現可能と思いますが、めんどくさい・・・
悩んだ自分はどうしたかというと、こうしました。
@FunctionalInterface
public interface JDIMouseClicked extends MouseListener {
void jdMouseClicked(MouseEvent e);
@Override
default void mouseReleased(MouseEvent e) {
}
@Override
default void mousePressed(MouseEvent e) {
}
@Override
default void mouseExited(MouseEvent e) {
}
@Override
default void mouseEntered(MouseEvent e) {
}
@Override
default void mouseClicked(MouseEvent e) {
jdMouseClicked(e);
}
}
インターフェースはデフォルトの実装ができるため、MouseListenerを実装した
インターフェースをすべてデフォルト実装をして、抽象メソッドを一個だけにすれば
関数型インターフェースになるということですね。
このインターフェースを必要なイベントの数だけ作成すれば、
マスコット側で楽にマウスの処理が実装できそうです。
マウスイベントの設定
上記の案でインターフェースを作成した後、マウスのイベントをマスコットに追加していきます。
移動はマウスのドラッグ時に現在のドラッグイベントの位置から最初にクリックした位置を
引き算すると移動後の位置が出てきます。
まずはクリックした際に、どこをクリックしたかを保存する必要があるため、
クリックイベントで位置を保存します。
/** クリック位置保持用 */
protected JDPoint clickPoint = new JDPoint(0, 0);
private void eventSetClickPoint(MouseEvent e) {
// クリック位置:X座標を取得
clickPoint.setX(e.getX());
// クリック位置:Y座標を取得
clickPoint.setY(e.getY());
}
JDPointクラスはただの値を保持しているだけのクラスです。
public final class JDPoint {
private int x;
private int y;
public JDPoint(int x, int y) {
this.x = x;
this.y = y;
}
/**
* xを取得します。
*
* @return x
*/
public int getX() {
return x;
}
/**
* xを設定します。
*
* @param x
*/
public void setX(int x) {
this.x = x;
}
/**
* yを取得します。
*
* @return y
*/
public int getY() {
return y;
}
/**
* yを設定します。
*
* @param y
*/
public void setY(int y) {
this.y = y;
}
}
次はドラッグ時の処理を作成していきます。
ドラッグ時は先ほどの通り、現在のイベント位置から最初のクリック位置を引き算して
その位置に座標を変更するようにします。
private void eventMoveWindow(MouseEvent e) {
var moveX = e.getXOnScreen() - clickPoint.getX();
var moveY = e.getYOnScreen() - clickPoint.getY();
this.setLocation(moveX, this.getY());
this.setLocation(this.getX(), moveY);
}
ここでは何もチェックしていないですが、画面外にマスコットが出ていかないように
チェック処理などを入れるとよいかもしれません。
最後に、追加した処理をマウスイベントに設定します。
設定するメソッドはコンストラクタで呼び出すことにします。
/** クリック位置保持用 */
public JDMascot() {
// ウィンドウの設定
setUp();
// ※今回追加した箇所
// イベントの登録
setMascotEvent();
}
private void setMascotEvent() {
// クリックイベント
JDIMousePressed eventSetClickPoint = e -> { eventSetClickPoint(e); };
this.addMouseListener(eventSetClickPoint);
// ドラッグイベント
JDIMouseDragged eventMoveWindowDragged = e -> { eventMoveWindow(e); };
this.addMouseMotionListener(eventMoveWindowDragged);
}
テストコードの作成
では、前回作成したテストコードを使用してマウス操作が
できるようになったかを確認します。
テストコードは新規で作成していません。
うむ。
終わりに
今回はマウスの操作をできるように実装しました。
次回はアプリケーションの終了を実装する予定です。