9
4

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 5 years have passed since last update.

MATLABでお絵描きツールを作ってみた(2) (ボタンで各種設定)

Last updated at Posted at 2019-08-22

前回のおさらい

前回は、簡単なお絵描きツールとして、マウス操作をキャプチャするfigureのコールバック関数を中心に紹介しました。

今回の内容

せっかくなので、「消去」「画像保存」「線の色変更」「線の太さ変更」ができるように、お絵描きツールを拡張します。
ポイントとなる技術は、ボタンの作成と、各種ダイアログの使用です。

共通変数の追加

前準備として、線の色と線の幅の設定を保存するための変数を追加します。
ここでは、コールバック関数をネスト関数とすることで、共通に呼び出せるようにします。

    LineColor   = [0,0.4470,0.7410]; % Lineの色
    LineWidth   = 1;                 % Lineの線幅

線を描画するところも以下のように変更し、色と線幅を指定するようにします。

curLineH = line(axH,curLineX,curLineY,'Color',LineColor,'LineWidth',LineWidth);

ボタンの配置

axes 表示域を少し小さくして、ウィンドウの下にボタンを配置します。
figure上のボタンは、uicontrol で Style をpushbutton に指定して作成します。
なお、uicontrol のStyle のデフォルト設定が、pushbutton なので、Style指定は省略することもできます。

axes の更新

前回のコードを以下のように少し修正します。
Position を変更して、figureの下部分に、ボタンを表示する領域を確保します。
また、画像保存するときに、枠表示が邪魔になるので、XAxis, YAxisのColorの指定を'none' にします。

%% Axesの表示
axH               = axes(figH);    % axH: 軸オブジェクト
axH.XTick         = [];            % X軸目盛をオフ
axH.YTick         = [];            % Y軸目盛をオフ
axH.Units         = 'normalized';  % Positionの単位指定
axH.Position      = [0,0.1,1,0.9]; % Axesの位置指定 (下10%の領域はボタン用に残す)
axH.XLim          = [0,1];         % X軸範囲を指定
axH.YLim          = [0,1];         % Y軸範囲を指定
axH.XAxis.Color   ='none';         % 枠を無色に指定
axH.YAxis.Color   ='none';         % 枠を無色に指定

ボタンの作成

例えば、「消去」用のボタンは、uicontrol を使って、以下のように設定します。
ボタンに表示する文字は、Stringで指定し、またボタン押下時のコールバック関数は、Callback に指定します。

% 消去ボタン
btnClearH = uicontrol(figH);              % btnClearH :「消去」のボタンオブジェクト
btnClearH.Units    = 'normalized';        % Position の単位指定
btnClearH.Position = [0,0,0.1,0.1];       % ボタンの位置指定
btnClearH.String   = '消去';              % 表示文字列の指定
btnClearH.Callback = @Callback_btnClearH; % コールバック関数の指定

コールバック関数の指定

コールバック関数には、ボタン押下時の処理を記載します。

「消去」ボタンのコールバック

findobj で axes 上の Lineを探索し、deleteですべて消去するようにします。

    function Callback_btnClearH(~,~)
        %% 消去ボタンのコールバック
        delete(findobj(axH,'Type','Line'));  % Axes上にあるLineをすべて消去
    end

「保存」ボタンのコールバック

画像としてファイルに保存するため、まず、ファイル名を取得します。
便利なダイアログがすでにあり、uiputfile を使ってファイル名を指定させます。
ファイル名が指定されれば、print を使ってファイルに保存します。

    function Callback_btnSaveH(~,~)
        %% 保存ボタンのコールバック        
        [FileName,PathName] = uiputfile('*.png','保存ファイル名'); % ファイル名の指定
        if ischar(FileName)
            % キャンセルでない場合
            print(figH,'-dpng','-noui',fullfile(PathName,FileName));
        end
    end

ファイル指定のダイアログは、次のようなものが立ち上がります。

uiputfile1.png

「線色」のコールバック

線の色を変更するために、色を指定します。
色の指定にも、便利なダイアログがあり、uisetcolor を使って指定します。

    function Callback_btnLineColorH(~,~)
       %% 線色のコールバック
       % ダイアログで色の指定
        RGB = uisetcolor(LineColor);
        if length(RGB)==3
            % キャンセルでない場合
            LineColor = RGB;
        end
    end

色の指定は、次のようなダイアログが立ち上がります。

uisetcolor2.png

「線幅」のコールバック

線の幅(太さ)を指定します。
ここでは、簡単のため、inputdlg を使って入力します。
inputdlg の結果は文字列になるため、数値に変換します。

    function Callback_btnLineWidthH(~,~)
       %% 線幅のコールバック
       % ダイアログで線幅の指定
        WidthStr = inputdlg('線幅','',1,{num2str(LineWidth)});
        if ~isempty(WidthStr)
            % キャンセルでない場合
            
            % 文字列から数値に変換
            Width = str2double(WidthStr);
            if ~isnan(Width)
                % 数値に変換できたとき線幅を変更
                LineWidth = Width;
            end
        end
    end

線の指定では、次のようなダイアログが立ち上がります。

inputdlg2.png

完成したプログラム

実行しやすいようにプログラム全体を表示します。

simple_draw2.m
function simple_draw2()

%% 共通変数の定義
ButtonState = false;             % マウスボタンの押下状態
curLineH    = gobjects();        % 現在のLineのオブジェクト
curLineX    = [];                % 現在のLineのX座標
curLineY    = [];                % 現在のLineのY座標
LineColor   = [0,0.4470,0.7410]; % Lineの色
LineWidth   = 1;                 % Lineの線幅

%% Figureの表示
figH                       = figure();                     % figH: Figureオブジェクト
figH.MenuBar               = 'none';                       % メニューをオフ
figH.WindowButtonDownFcn   = @WindowButtonDownFcn_figH;    % マウスボタン押下時のコールバック関数を指定
figH.WindowButtonMotionFcn = @WindowButtonMotionFcn_figH;  % マウスボタン移動時のコールバック関数を指定
figH.WindowButtonUpFcn     = @WindowButtonUpFcn_figH;      % マウスボタンリリース時のコールバック関数を指定

%% Axesの表示
axH               = axes(figH);    % axH: 軸オブジェクト
axH.XTick         = [];            % X軸目盛をオフ
axH.YTick         = [];            % Y軸目盛をオフ
axH.Units         = 'normalized';  % Positionの単位指定
axH.Position      = [0,0.1,1,0.9]; % Axesの位置指定 (下10%の領域はボタン用に残す)
axH.XLim          = [0,1];         % X軸範囲を指定
axH.YLim          = [0,1];         % Y軸範囲を指定
axH.XAxis.Color   ='none';         % 枠を無色に指定
axH.YAxis.Color   ='none';         % 枠を無色に指定

%% ボタン
% 消去ボタン
btnClearH = uicontrol(figH);              % btnClearH :「消去」のボタンオブジェクト
btnClearH.Units    = 'normalized';        % Position の単位指定
btnClearH.Position = [0,0,0.1,0.1];       % ボタンの位置指定
btnClearH.String   = '消去';              % 表示文字列の指定
btnClearH.Callback = @Callback_btnClearH; % コールバック関数の指定

% 保存ボタン
btnSaveH = uicontrol(figH);              % btnSaveH :「保存」のボタンオブジェクト
btnSaveH.Units    = 'normalized';        % Position の単位指定
btnSaveH.Position = [0.1,0,0.1,0.1];     % ボタンの位置指定
btnSaveH.String   = '保存';              % 表示文字列の指定
btnSaveH.Callback = @Callback_btnSaveH;  % コールバック関数の指定

% 線色ボタン
btnLineColorH = uicontrol(figH);                   % btnLineColorH :「線色」のボタンオブジェクト
btnLineColorH.Units    = 'normalized';             % Position の単位指定
btnLineColorH.Position = [0.2,0,0.1,0.1];          % ボタンの位置指定
btnLineColorH.String   = '線色';                   % 表示文字列の指定
btnLineColorH.Callback = @Callback_btnLineColorH;  % コールバック関数の指定

% 線幅ボタン
btnLineWidthH = uicontrol(figH);                   % btnLineWidthH :「線幅」のボタンオブジェクト
btnLineWidthH.Units    = 'normalized';             % Position の単位指定
btnLineWidthH.Position = [0.3,0,0.1,0.1];          % ボタンの位置指定
btnLineWidthH.String   = '線幅';                   % 表示文字列の指定
btnLineWidthH.Callback = @Callback_btnLineWidthH;  % コールバック関数の指定

    %% コールバック関数の定義
    function WindowButtonDownFcn_figH(~,~)
        %% マウスボタン押下時のコールバック        
        ButtonState = true; % 押下状態を保存

        % マウスの位置の取得
        curLineX = axH.CurrentPoint(1,1);
        curLineY = axH.CurrentPoint(1,2);

        % 線の描画
        curLineH = line(axH,curLineX, curLineY,'Color',LineColor,'LineWidth',LineWidth);
    end

    function WindowButtonMotionFcn_figH(~,~)
        %% マウスボタン移動時のコールバック
        if ButtonState
            % マウスボタンを押下時には、Lineの描画を更新

            % 現在のマウスの位置
            X = axH.CurrentPoint(1,1);
            Y = axH.CurrentPoint(1,2);
            
            % 線の座標値を更新
            curLineX = [curLineX;X];
            curLineY = [curLineY;Y];

            % 描画の更新
            curLineH.XData = curLineX;
            curLineH.YData = curLineY;
        end
    end

    function WindowButtonUpFcn_figH(~,~)
        %% マウスボタンリリース時のコールバック
        ButtonState = false;  % ボタン押下状態を解除
    end

    function Callback_btnClearH(~,~)
        %% 消去ボタンのコールバック
        delete(findobj(axH,'Type','Line'));  % Axes上にあるLineをすべて消去
    end
    
    function Callback_btnSaveH(~,~)
        %% 保存ボタンのコールバック        
        [FileName,PathName] = uiputfile('*.png','保存ファイル名'); % ファイル名の指定
        if ischar(FileName)
            % キャンセルでない場合
            print(figH,'-dpng','-noui',fullfile(PathName,FileName));
        end
    end

    function Callback_btnLineColorH(~,~)
       %% 線色のコールバック
       % ダイアログで色の指定
        RGB = uisetcolor(LineColor);
        if length(RGB)==3
            % キャンセルでない場合
            LineColor = RGB;
        end
    end

    function Callback_btnLineWidthH(~,~)
       %% 線幅のコールバック
       % ダイアログで線幅の指定
        WidthStr = inputdlg('線幅','',1,{num2str(LineWidth)});
        if ~isempty(WidthStr)
            % キャンセルでない場合
            
            % 文字列から数値に変換
            Width = str2double(WidthStr);
            if ~isnan(Width)
                % 数値に変換できたとき線幅を変更
                LineWidth = Width;
            end
        end
    end

end

実行例

起動するとボタン付きの figureが表示されます。

figure2.png

実際に絵を描いてみます。(相変わらず絵心がなくてすみません。。。)

image2.png

終わりに

この例では、uicontrol を使って、figure上にボタンを配置してお絵描きツールを拡張しました。
uiputfile, uisetcolor, inputdlg といったダイアログを使用することで、各ボタンの操作も簡単に記述できました。
他にも、背景色の変更やグリッドの表示、等、いろんな機能を追加することもできると思います。
よくある子供向けのお絵描きアプリには、書いた絵が動くようなものも多いので、そのような実装も可能でしょう。以上を参考に様々なアイデアを実装してみてください!

9
4
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
9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?