8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【MATLAB/AppDesigner】波形をマウスドラッグで範囲選択する

Last updated at Posted at 2020-06-17

#はじめに
音楽編集ソフトでよくある,波形をクリック→ドラッグして範囲選択するというのを実装したい.

今回はpatch関数を使用して実装を行う.

#ググる
ググったら殆どやりたいことに近いものが出てきた.
App Designer で作成した GUI において,マウスの操​作でグラフィックスオ​ブジェクトを動かすこ​とはできますか?

1 つ以上の塗りつぶされた多角形領域のプロット - MATLAB patch

これを参考に作成する.

#AppDesigner実装
以下実装をまとめる.

##コンポーネント配置
以下のコンポーネントを適当に配置する.

コンポーネント名 説明
UIAxes グラフを表示する
OpenFileDialogButton ファイルダイアログを開く
FilePathEditField ファイル名を表示
component.png

##メンバ変数

変数名 説明
h patchオブジェクト
mouseStatus マウスクリック状態
clickPos クリックした座標

##コールバック関数
###起動時初期化処理

startupFcn
function startupFcn(app)
% グラフをセットアップ
xlabel(app.UIAxes, '時間[s]');
ylabel(app.UIAxes, '振幅');
% ツールバーを無効にする
app.UIAxes.Toolbar.Visible = 'off';
% 座標軸の組み込み操作を無効にする
disableDefaultInteractivity(app.UIAxes);
% マウス状態を初期化
mouseStatus = "ButtonUp";
end

###ファイル開くボタン押下時
グラフの間引き表示処理として前回投稿した
【MATLAB】plot表示時間短縮のためにデータを間引く
で作成したDecimationProcを使用する.
(間引き表示しないと表示が重たすぎるので)

OpenFileDialogButtonPushed
function OpenFileDialogButtonPushed(app, event)
% ファイルダイアログを開く
[file1, path1] = uigetfile({'*.wav;*.mp3','Audio Files (*.wav,*.mp3)'});
if(file1 == 0)
    % キャンセルで閉じた場合
    return
end

% ファイル名をエディットボックスに格納
app.FilePathEditField.Value = file1;

% ファイルを開いてメンバ変数に格納
[y, Fs] = audioread(fullpath1);
y = y(:, 1);% ステレオの場合は片側だけ使用
decimation = 5000;
y = app.DecimationProc(y, decimation);
Fs = Fs/decimation;

% 時間波形をプロット
N = length(y);
t = ((1:N)-1)/Fs;
plot(app.UIAxes, t, y);

% patchオブジェクトを作成
app.h = patch(app.UIAxes,[0, 0, 0, 0],[0, 0, 0, 0],'r');
set(app.h,'FaceAlpha', 0.3); % 透明度
end

マウスボタン押下時の処理

UIFigureWindowButtonDown
function UIFigureWindowButtonDown(app, event)
app.mouseStatus = "ButtonDown";
app.clickPos = app.UIAxes.CurrentPoint;
% クリック位置が範囲外の場合は範囲内に調整
% clamp処理とか言うらしいですね,よく分かりませんが・・・
if(app.clickPos(1,1) < app.UIAxes.XLim(1))
    app.clickPos(1,1) = app.UIAxes.XLim(1);
end
if(app.clickPos(1,1) > app.UIAxes.XLim(2))
    app.clickPos(1,1) = app.UIAxes.XLim(2);
end
% patch描画を消す
app.h.XData = [0, 0, 0, 0];
end

###マウスボタンを離した時の処理

UIFigureWindowButtonUp
function UIFigureWindowButtonUp(app, event)
app.mouseStatus = "ButtonUp";
end

###マウスを移動中の処理
これが本記事でのメインの処理である.
マウスをクリックした位置から現在カーソルの範囲を赤色で重畳表示を行う.

UIFigureWindowButtonMotion
function UIFigureWindowButtonMotion(app, event)
if(app.mouseStatus ~= "ButtonDown")
    return
end
Cp = app.UIAxes.CurrentPoint; % get current mouse point on Axes
if(Cp(1,1) < app.UIAxes.XLim(1))
    Cp(1,1) = app.UIAxes.XLim(1);
end
if(Cp(1,1) > app.UIAxes.XLim(2))
    Cp(1,1) = app.UIAxes.XLim(2);
end
app.h.XData = [app.clickPos(1,1), Cp(1,1), Cp(1,1), app.clickPos(1,1)]; % Update xdata for patch object
drawnow
end

#結果
ドラッグしたところ,いい感じに範囲選択が出来た.

##結果をGIFで
GIFで見ると結果がよく伝わると思うが,かなり重たいので実用レベルでは無いかも.
まぁ,これはキャプチャソフトで録画しながらMATLABアプリを動かしてたのでより重たくなっていたので,録画していない時はもうちょっとサクサクに動くわよ.

8
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?