デスクトップマスコットを作ってみる。【マウスの操作編】

# 初めに
前回の記事ではマスコットの表示と反転までを作成しました。

今回はマウスで動かせるように処理を追加していこうと思います。
JavaFXで行っていた時と異なり、マウスイベントについて実装を変える必要があったので
そのあたりが中心になります。









# MouseListenerの関数型インターフェース化
JavaFXで作成していたころはFxmlにイベントを定義していましたが、
今回からはSwingを使用しているため、同じようにはいきません。

JFrameのマウスイベントを設定するためには**MouseListener**インターフェースを
実装する必要があります。

このインターフェースにはマウス操作の必要なメソッドがずらっと定義されています。
これは関数型インターフェースではないため、ラムダで記述できないのです。

マウスイベントごとに実装クラスを作成したり、何かしらの条件分岐を作れば
実現可能と思いますが、めんどくさい・・・

悩んだ自分はどうしたかというと、こうしました。

```java:JDIMouseClicked.java

@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を実装した
インターフェースをすべてデフォルト実装をして、抽象メソッドを一個だけにすれば
関数型インターフェースになるということですね。

このインターフェースを必要なイベントの数だけ作成すれば、
マスコット側で楽にマウスの処理が実装できそうです。













# マウスイベントの設定
上記の案でインターフェースを作成した後、マウスのイベントをマスコットに追加していきます。

移動はマウスのドラッグ時に**現在のドラッグイベントの位置**から**最初にクリックした位置**を
引き算すると移動後の位置が出てきます。

まずはクリックした際に、どこをクリックしたかを保存する必要があるため、
クリックイベントで位置を保存します。

```JDMascot.java

/** クリック位置保持用 */
protected JDPoint clickPoint = new JDPoint(0, 0);

private void eventSetClickPoint(MouseEvent e) {
    // クリック位置：X座標を取得
    clickPoint.setX(e.getX());
    // クリック位置：Y座標を取得
    clickPoint.setY(e.getY());
}

```

**JDPoint**クラスはただの値を保持しているだけのクラスです。

```java:JDPoint.java

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;
    }
}

```

次はドラッグ時の処理を作成していきます。
ドラッグ時は先ほどの通り、現在のイベント位置から最初のクリック位置を引き算して
その位置に座標を変更するようにします。

```java:JDMascot.java

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);
}

```

ここでは何もチェックしていないですが、画面外にマスコットが出ていかないように
チェック処理などを入れるとよいかもしれません。

最後に、追加した処理をマウスイベントに設定します。
設定するメソッドはコンストラクタで呼び出すことにします。

```java:JDMascot.java

/** クリック位置保持用 */
public JDMascot() {
    // ウィンドウの設定
    setUp();

    // ※今回追加した箇所
    // イベントの登録
    setMascotEvent();
}

private void setMascotEvent() {
    // クリックイベント
    JDIMousePressed eventSetClickPoint = e -> { eventSetClickPoint(e); };
    this.addMouseListener(eventSetClickPoint);

    // ドラッグイベント
    JDIMouseDragged eventMoveWindowDragged = e -> { eventMoveWindow(e); };
    this.addMouseMotionListener(eventMoveWindowDragged);
}

```











# テストコードの作成

では、前回作成したテストコードを使用してマウス操作が
できるようになったかを確認します。

テストコードは新規で作成していません。

![Videotogif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555408/3a3e9f70-fc4b-5c99-b8db-407736a27231.gif)

うむ。











# 終わりに
今回はマウスの操作をできるように実装しました。
次回はアプリケーションの終了を実装する予定です。






# リンク
- [デスクトップマスコットを作ってみる。【目次】](https://qiita.com/urado/items/4a810c457cb862e370e8)