【MATLAB/AppDesigner】 マウスを使ってオブジェクトを動かす その1

# 概要
MATLABにはAppDesignerという簡単にGUIアプリを作れる優れた機能がある.
今回はAppDesignerを使って，マウスでオブジェクトを動かすプログラムを紹介する．

- その１：四角形のpatchオブジェクトを動かすプログラム ← この記事
- その２：[上記を発展させて3点からなる三角形の内接円を描画するプログラム](https://qiita.com/hiropon_matlab/items/7dcb724d163748ac28a4)

参考記事
[App Designer で作成した GUI において，マウスの操​作でグラフィックスオ​ブジェクトを動かすこ​とはできますか？](https://jp.mathworks.com/matlabcentral/answers/480221-app-designer-gui)
[【MATLAB/AppDesigner】波形をマウスドラッグで範囲選択する](https://qiita.com/dokagui_tairan/items/5d6d1302698659d4d9f8)
[【MATLAB】カーソルを追いかけるプロットの作り方](https://qiita.com/eigs/items/d2c5d53298b2dc5197bf)
[MATLABでお絵描きツールを作ってみた （マウス操作イベントに応じたプログラム例）](https://qiita.com/sanmojih/items/5ac9ed1510da863d42f2)

# AppDesigner の設定
AppDesigner自体の説明は公式ドキュメンテーションや以下が参考になる．
[MATLABで簡単にGUIを作ろう！](https://qiita.com/griffin921/items/d761abc656542f62a611)

今回は四角形を動かすだけなので，座標軸を１つ配置するだけでOK．
![Interface1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2665079/c28c9d69-055d-7739-0196-f2e7050d6dd3.png)


# プロパティと関数の設定
コンポーネントが配置できたら設置ビューからコードビューに移る．
AppDesigner上の挿入ボタンをクリックして，プロパティと関数を追加する．
![InkedInterface0_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2665079/dc6534a6-6b76-2c0e-10c4-26a8073e8c6f.jpeg)

## プライベートプロパティの設定
今回は四角形をpatchオブジェクトで描画する．
そこでグラフィックオブジェクト用のプロパティとして```square1```として用意し，patchオブジェクトをここに格納することを考える．
これにより，マウス操作時にコールバックする関数からもpatchオブジェクトにアクセスできるようにしている．
```matlab
properties (Access = private)
    square1
end
```
## プライベート関数の設定
マウス操作を受け取る関数を用意する．
オブジェクトを左クリックしたときにコールバックする関数：```leftButtonDown(app)```，
ドラッグ時にコールバックする関数：```windowButtonMove(app)```，
クリックを離したときのコールバックする関数：```leftButtonUp(app)```，
の３つの関数をプライベート関数として作成する．
```matlab
methods (Access = private)

    function leftButtonDown(app)
        disableDefaultInteractivity(app.UIAxes)
        seltype = app.UIFigure.SelectionType;
        if strcmp(seltype,'normal') %'normal':左クリック 'alt':右クリック 'open'：ダブルクリック
            app.UIFigure.Pointer = 'circle'; %ポインタの種類変更
            app.UIFigure.WindowButtonMotionFcn = @(~,~)windowButtonMove(app);
            app.UIFigure.WindowButtonUpFcn = @(~,~)leftButtonUp(app);
        end
    end

    function windowButtonMove(app)
        x = app.UIAxes.CurrentPoint(1,1); %マウス位置取得
        y = app.UIAxes.CurrentPoint(1,2);
        app.square1.XData = [x-1/2 x+1/2 x+1/2 x-1/2]; %patchオブジェクトの座標更新
        app.square1.YData = [y-1/2 y-1/2 y+1/2 y+1/2];
    end

    function leftButtonUp(app)
        app.UIFigure.Pointer = 'arrow';
        app.UIFigure.WindowButtonMotionFcn = '';
        app.UIFigure.WindowButtonUpFcn = '';
        enableDefaultInteractivity(app.UIAxes)
    end

end
```
## 起動時にコールバックされる関数の設定
起動時にコールバックされる```startupFcn(app)```を記述する．
patchオブジェクトに予め割り当てられているプロパティ```'ButtonDownFcn'```に，先ほど作成した```leftButtonDownFnc(app)```を設定するのが重要．
```matlab
function startupFcn(app)
            
    app.square1 = patch(app.UIAxes, [0 1 1 0], [0 0 1 1], 'red');
    set(app.square1, 'ButtonDownFcn', @(~,~)leftButtonDown(app))
            
    xlim(app.UIAxes, [-10 10]), ylim(app.UIAxes, [-10 10])
    daspect(app.UIAxes, [1 1 1])
end
```
以上でプログラムは終わり．上からコピペするだけで再現可能です．
たったこれだけの行数でマウス操作を実装できるのは毎回驚く！

# 実行
実行すると赤色の正方形が描画される．
正方形をドラッグ＆ドロップすると正方形の位置を移動できる．
![Animation4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2665079/adf5e816-b614-0029-740b-15291a6c965a.gif)


# おわりに
今回のポイントは，オブジェクトの 'ButtonDownFcn' プロパティに関数ハンドルを代入である．
['ButtonDownFcn' に関連する公式ドキュメンテーション](https://jp.mathworks.com/help/matlab/creating_plots/button-down-callback-function.html)
これにより，オブジェクトをつかんで動かし離すという操作が可能となった．

[次回](https://qiita.com/hiropon_matlab/items/7dcb724d163748ac28a4)は，四角の数を3つに増やして3点からなる三角形を作成し，三角形の内接円をリアルタイムに描画するプログラムを紹介する．