Main Content

プログラムによるカスタム UI コンポーネントの開発

カスタム UI と可視化を作成するために、複数のグラフィックス オブジェクトと UI オブジェクトを組み合わせたり、それらのプロパティを変更したり、追加の関数を呼び出したりすることができます。R2020a 以前のリリースでは、カスタマイズ コードを保存し他者と共有する一般的な方法は、スクリプトまたは関数の作成です。

R2020b 以降は、スクリプトや関数の代わりに、ComponentContainer 基底クラスのサブクラスを定義することで UI コンポーネントのクラス実装を作成することができます。クラスの作成には以下の利点があります。

  • カスタマイズが簡単 — ユーザーが UI コンポーネントの特性をカスタマイズする場合、コードの変更と再実行を行うことなしに、プロパティを設定することができます。ユーザーはコマンド ラインでプロパティを変更したり、プロパティ インスペクターでプロパティを確認できます。

  • カプセル化 — コードをこの方法で整理することで、ユーザーに対し実装の詳細を非表示にすることができます。計算を実行し、基となるグラフィックス オブジェクトを管理するメソッドを実装します。

このトピックは、プログラムでクラスを定義することでカスタム UI コンポーネントを作成する手順の概要を示したものです。R2022a 以降では、代わりに App Designer を使用して対話形式でカスタム UI コンポーネントを作成できます。対話形式による方法の詳細については、Create a Simple Custom UI Component in App Designerを参照してください。

UI コンポーネント クラスの構造

UI コンポーネント クラスには、いくつかの必須部分と、いくつかのオプション部分があります。

UI コンポーネント クラスの最初の行では、matlab.ui.componentcontainer.ComponentContainer クラスをスーパークラスとして指定します。たとえば、ColorSelector というクラスの最初の行は次のようになります。

classdef ColorSelector < matlab.ui.componentcontainer.ComponentContainer

スーパークラスの指定に加えて、以下のコンポーネントをユーザー クラス定義に含めます。いくつかのコンポーネントは必須で、他のコンポーネントは推奨またはオプションです。

コンポーネント説明

パブリック プロパティ ブロック
(推奨)

このブロックは、ユーザーがアクセスできるすべてのプロパティを定義します。これらのプロパティが一緒になって、UI コンポーネントのユーザー インターフェイスを構成します。

プライベート プロパティ ブロック
(推奨)

このブロックは、ユーザーがアクセスできない、基となるグラフィックス オブジェクトや他の実装詳細を定義します。

このブロックでは、以下の属性値が設定されます。

  • Access = private

  • Transient

  • NonCopyable

イベント ブロック
(オプション)

このブロックは、この UI コンポーネントがトリガーするイベントを定義します。

このブロックでは、以下の属性値が設定されます。

  • HasCallbackProperty

  • NotifyAccess = protected

HasCallbackProperty 属性が設定されると、MATLAB® はブロック内のイベントごとにパブリック プロパティを作成します。そのパブリック プロパティには、イベントが発生すると実行される、ユーザー指定のコールバックが保存されます。

setup メソッド
(必須)

このメソッドは、UI コンポーネントの初期状態を設定します。MATLAB がオブジェクトを作成すると 1 回実行されます。

このメソッドは、保護された methods ブロック内で定義します。

update メソッド
(必須)

このメソッドは、UI コンポーネント内の基となるオブジェクトを更新します。以下の条件で実行されます。

  • 次回の drawnow の実行中、ユーザーが 1 つ以上のプロパティ値を変更した後

  • ユーザーのグラフィックス環境の特性 (サイズなど) が変更されたとき

このメソッドは、setup メソッドと同じ保護されたブロック内で定義します。

コンストラクター メソッド

コンストラクターは ComponentContainer 基底クラスから継承されるため、ユーザー クラスにコンストラクター メソッドを作成する必要はありません。継承されたコンストラクターは、オプションの入力引数 (親コンテナーと、UI コンポーネントにプロパティを設定するための任意数の名前と値のペアの引数) を受け入れます。たとえば、パブリック プロパティ Value および ValueChangedFcn をもつ ColorSelector というクラスを定義する場合、次のコードを使用してユーザー クラスのインスタンスを作成できます。

f = uifigure; 
c = ColorSelector(f,'Value',[1 1 0],'ValueChangedFcn',@(o,e)disp('Changed'))

別の構文または別の動作をもつコンストラクターを指定する場合は、カスタム コンストラクター メソッドを定義できます。カスタム コンストラクターの例は、チャート クラスのコンストラクターの作成を参照してください。

パブリックおよびプライベートのプロパティ ブロック

ユーザー クラスのプロパティを、少なくとも 2 つのブロック間で分割します。

  • ユーザー向けインターフェイスのコンポーネントを保存するためのパブリック ブロック

  • 非表示にする実装の詳細を保存するためのプライベート ブロック

パブリック ブロックに収められるプロパティは、ユーザーの指定する入力値を保存します。たとえば、ユーザーがカラー値を選択できる UI コンポーネントでは、パブリック プロパティにカラー値が保存されている可能性があります。プロパティの名前と値のペアの引数は暗黙的なコンストラクター メソッドのオプション入力であるため、パブリック プロパティを既定値に初期化する方法が推奨されます。

プライベート ブロックに収められるプロパティには、保存するすべての計算値に加えて、UI コンポーネントを構成する基となるグラフィックス オブジェクトが保存されます。最終的に、ユーザー クラスはパブリック プロパティ内のデータを使用して、基となるオブジェクトを構成します。プライベート ブロックに Transient 属性と NonCopyable 属性を設定することで、ユーザーが UI コンポーネントのインスタンスのコピーや保存をする場合に、冗長な情報が保存されることを回避します。

たとえば、次に示すのは、ユーザーがカラー値を選択できる UI コンポーネントのプロパティ ブロックです。パブリック プロパティ ブロックには、ユーザーが制御できる値としてカラー値が保存されています。プライベート プロパティ ブロックには、グリッド レイアウト マネージャー、ボタン、編集フィールドの各オブジェクトが保存されています。

properties
    Value {validateattributes(Value, ...
        {'double'},{'<=',1,'>=',0,'size',[1 3]})} = [1 0 0];   
end

properties (Access = private,Transient,NonCopyable)
    Grid matlab.ui.container.GridLayout 
    Button matlab.ui.control.Button 
    EditField matlab.ui.control.EditField
end   

イベント ブロック

オプションとして、UI コンポーネントが発生させるイベント用に 3 番目のブロックを追加することができます。

HasCallbackProperty 属性を指定することにより、ブロック内に各イベントのパブリック プロパティを作成します。そのパブリック プロパティには、イベントが発生すると実行される、ユーザー指定のコールバックが保存されます。パブリック プロパティの名前は、イベント名に文字 Fcn を追加したものとなります。たとえば、ユーザーがカラー値を選択できる UI コンポーネントがイベント ValueChanged を定義するならば、これによって、対応するパブリック プロパティ ValueChangedFcn が生成されます。notify メソッドを使用してイベントを発生させ、プロパティ内のコールバックを実行します。

たとえば、ユーザーがカラー値を選択できる UI コンポーネントに対するイベント ブロックは、次のようになります。

events (HasCallbackProperty, NotifyAccess = protected) 
    ValueChanged 
end 
ユーザーがカラー値を選択すると、notify メソッドが呼び出されて ValueChanged イベントが発生し、ValueChangedFcn プロパティ内のコールバックが実行されます。
function getColorFromUser(comp)
    c = uisetcolor(comp.Value);
    if (isscalar(c) && (c == 0))
        return;
    end
    
    % Update the Value property
    oldValue = comp.Value;
    comp.Value = c;

    % Execute user callbacks and listeners
    notify(comp,'ValueChanged');
end
ユーザーが UI コンポーネントのインスタンスを作成する際には、生成されたパブリック プロパティを使用して、カラー値が変更されると実行されるコールバックを指定することができます。
f = uifigure; 
c = ColorSelector(f,'ValueChangedFcn',@(o,e)disp('Changed'))
プロパティに対するコールバックの指定の詳細については、プログラムで作成したアプリ用のコールバックの作成を参照してください。

setup メソッド

クラスに setup メソッドを定義します。setup メソッドは、MATLAB が UI コンポーネント オブジェクトを作成するときに一度実行されます。名前と値の引数としてコンストラクター メソッドに渡されたプロパティ値は、このメソッドの実行後に割り当てられます。

次の場合に setup メソッドを使用します。

  • コンポーネントを構成するグラフィックス オブジェクトと UI オブジェクトを作成する。

  • オブジェクトをプライベート プロパティとしてコンポーネント オブジェクト上に保存する。

  • オブジェクトの配置と構成を行う。

  • コンポーネント内で有用な動作をするよう、オブジェクトを互いにつなげる。

setup メソッドは、保護されたブロック内で定義します。

ほとんどの UI オブジェクト作成関数には、親を指定するためのオプションの入力引数があります。クラス メソッド内からこれらの関数を呼び出す際には、ターゲットの親を指定しなければなりません。設定する UI コンポーネント オブジェクトとして、メソッドに渡されるクラス インスタンスの引数を使用してターゲットの親を指定します。

たとえば、次のプロパティをもつ UI コンポーネントについて考えます。

  • Value という 1 つのパブリック プロパティ

  • GridButton、および EditField という 3 つのプライベート プロパティ

setup メソッドでは、UI コンポーネントのインスタンス (comp) をターゲットの親として指定し、関数 uigridlayoutuieditfielduibutton を呼び出して各プライベート プロパティの基となるグラフィックス オブジェクトを作成します。

function setup(comp) 
    % Create grid layout to manage building blocks 
    comp.Grid = uigridlayout(comp,[1 2],'ColumnWidth',{'1x',22},... 
        'RowHeight',{'fit'},'ColumnSpacing',2,'Padding',2); 

    % Create edit field for entering color value
    comp.EditField = uieditfield(comp.Grid,'Editable',false,... 
        'HorizontalAlignment','center'); 

    % Create button to confirm color change
    comp.Button = uibutton(comp.Grid,'Text',char(9998), ... 
        'ButtonPushedFcn',@(o,e) comp.getColorFromUser()); 
end 

update メソッド

ユーザー クラスに update メソッドを定義します。このメソッドは、UI コンポーネント オブジェクトが値の変化に応じてその外観を変える必要がある場合に実行されます。

update メソッドを使用して、プロパティの新しい値を基に、UI コンポーネント内の基となるグラフィックス オブジェクトを再構成します。通常、このメソッドではどのプロパティが変更されたかを判定しません。プロパティに依存する、基となるグラフィックス オブジェクトのすべての特性が再構成されます。

たとえば、次のプロパティをもつ UI コンポーネントについて考えます。

  • Value という 1 つのパブリック プロパティ

  • GridButton、および EditField という 3 つのプライベート プロパティ

update メソッドは、Value に保存されている色を使って EditField オブジェクトと Button オブジェクトの BackgroundColor を更新します。update メソッドはまた、色の数値表現によっても EditField オブジェクトを更新します。この方法では、Value がどのように変更されても、その変更はあらゆる場所で等しく可視化されます。

function update(comp)      
    % Update edit field and button colors 
    set([comp.EditField comp.Button],'BackgroundColor',comp.Value, ... 
        'FontColor',comp.getContrastingColor(comp.Value));  

    % Update edit field display text 
    comp.EditField.Value = num2str(comp.Value,'%0.2g ');            

end

プロパティ値を変更してから、それら変更の結果が表示されるまでには遅延が生ずる場合があります。update メソッドは、setup メソッドの実行後に初めて実行され、その後は、drawnow が実行されるたびに実行されます。関数 drawnow は、ユーザーの MATLAB セッションにおけるグラフィックス環境の状態に基づき、定期的に自動実行されます。この定期的な実行は、遅延につながる可能性があります。

例: カラー セレクターの UI コンポーネント

この例では、このページの他の節で説明されているコードを使用して、色を選択するための UI コンポーネントを作成する方法を説明します。ColorSelectorComponent.m という名前のクラス定義ファイルを、MATLAB パス上にあるフォルダー内に作成します。以下の手順に従ってクラスを定義します。

手順実装

ComponentContainer 基底クラスから派生させます。

classdef ColorSelector < matlab.ui.componentcontainer.ComponentContainer

パブリック プロパティを定義します。

    properties
        Value {validateattributes(Value, ...
            {'double'},{'<=',1,'>=',0,'size',[1 3]})} = [1 0 0]; 
    end

パブリック イベントを定義します。

    events (HasCallbackProperty, NotifyAccess = protected) 
        ValueChanged % ValueChangedFcn will be the generated callback property 
    end

プライベート プロパティを定義します。

    properties (Access = private, Transient, NonCopyable) 
        Grid matlab.ui.container.GridLayout 
        Button matlab.ui.control.Button 
        EditField matlab.ui.control.EditField 
    end

setup メソッドを実装します。この場合、uigridlayoutuieditfielduibutton の各関数を呼び出して、GridLayoutEditFieldButton の各オブジェクトを作成します。これらのオブジェクトを、対応するプライベート プロパティに保存します。

getColorFromUser メソッドを、ボタンを押すと呼び出される ButtonPushedFcn コールバックとして指定します。

    methods (Access = protected) 
        function setup(comp) 
            % Grid layout to manage building blocks 
            comp.Grid = uigridlayout(comp,[1,2],'ColumnWidth',{'1x',22}, ... 
                'RowHeight',{'fit'},'ColumnSpacing',2,'Padding',2);              

            % Edit field for value display and button to launch uisetcolor 
            comp.EditField = uieditfield(comp.Grid,'Editable',false, ... 
                'HorizontalAlignment','center'); 
            comp.Button = uibutton(comp.Grid,'Text',char(9998), ... 
                'ButtonPushedFcn',@(o,e) comp.getColorFromUser()); 

        end

update メソッドを実装します。この場合、編集フィールドの基となるオブジェクトの背景色とテキストを更新してカラー値を表示します。

        function update(comp)     
            % Update edit field and button colors 
            set([comp.EditField comp.Button],'BackgroundColor',comp.Value, ... 
                'FontColor',comp.getContrastingColor(comp.Value));  

            % Update the display text 
            comp.EditField.Value = num2str(comp.Value,'%0.2g ');            
        end 
    end

プライベート メソッドを使用して、コールバックと他の要素をつなげます。

ボタン押下で getColorFromUser メソッドがトリガーされると、関数 uisetcolor が呼び出されてカラー ピッカーを開き、次に関数 notify が呼び出されてユーザーのコールバック関数とリスナー関数を実行します。

update メソッドによって getContrastingColor メソッドが呼び出されると、新しい背景色上で黒と白のいずれのテキストがより読みやすいかが計算されます。

    methods (Access = private) 
        function getColorFromUser(comp) 
            c = uisetcolor(comp.Value); 
            if (isscalar(c) && (c == 0)) 
                return; 
            end 
            
            % Update the Value property 
            comp.Value = c;              

            % Execute user callbacks and listeners
            notify(comp,'ValueChanged'); 
        end         
        function contrastColor = getContrastingColor(~,color) 
            % Calculate opposite color 
            c = color * 255; 
            contrastColor = [1 1 1]; 
            if (c(1)*.299 + c(2)*.587 + c(3)*.114) > 186 
                contrastColor = [0 0 0]; 
            end 
        end 
    end 
end

次に、いくつかのパブリック プロパティを指定して暗黙的なコンストラクター メソッドを呼び出すことで、UI コンポーネントのインスタンスを作成します。コールバックを、カラー値が変更されると Color changed という語が表示されるように指定します。

h = ColorSelector('Value', [1 1 0]); 
h.ValueChangedFcn = @(o,e) disp('Color changed');

Instance of the color selector UI component displaying the color yellow.

ボタンをクリックし、カラー ピッカーを使用して色を選択します。コンポーネントの外観が変わり、MATLAB は Color changed の語をコマンド ウィンドウに表示します。

Instance of the color selector UI component displaying the color blue.

参考

クラス

関数

関連するトピック