Main Content

コールバック間のデータ共有

アプリの UI コンポーネントのコールバック関数を記述して、ユーザーが操作するときの動作を指定できます (アプリのコールバック関数の詳細については、プログラムで作成したアプリ用のコールバックの作成を参照してください)。

相互に依存する複数の UI コンポーネントをもつアプリでは、コールバック関数からメインのアプリ関数内で定義されたデータにアクセスしたり、他のコールバックとデータを共有したりしなければならないことがよくあります。たとえば、リスト ボックスをもつアプリを作成する場合、アプリ ユーザーが選択したリスト ボックスのオプションに基づいてアプリのイメージを更新することがあります。各コールバック関数はそれぞれ固有のスコープをもつため、この関数にアクセスする必要があるアプリの各部分でリスト ボックスのオプションとイメージに関する情報を明示的に共有しなければなりません。そのためには、メインのアプリ関数を使用して、その情報をコールバックと共有できる方法で格納します。その後、コールバック関数内から情報にアクセスしたり情報を変更したりします。

アプリ データの格納

アプリの UI コンポーネントのプロパティには、役立つ情報が含まれています。たとえば、Value プロパティをクエリすると、スライダーの現在の位置がわかります。UI コンポーネントを作成する際は、プロパティの設定とアクセスをアプリ コード全体から行えるように、コンポーネントを変数として格納します。

事前定義されるプロパティのほかに、すべてのコンポーネントに UserData プロパティがあり、これを使用して任意の MATLAB® データを格納できます。UserData で一度に保持できる変数は 1 つのみですが、複数の値を構造体配列または cell 配列として格納できます。UserData を使用して、アプリの UI コンポーネントへのハンドルのほか、アプリ コード内から更新が必要になる可能性がある他のアプリ データも格納できます。1 つの方法として、メイン アプリの Figure ウィンドウの UserData プロパティにすべてのアプリ データを格納すると便利です。アプリのいずれかのコンポーネントにアクセスできれば、関数 ancestor を使用してメインの Figure ウィンドウにアクセスできます。そのため、各コンポーネントのコールバック内からアクセスできる場所にすべてのアプリ データが保持されることになります。

たとえば、次のコードは日付ピッカー コンポーネントをもつ Figure を作成します。Figure の UserData プロパティに、日付ピッカーと今日の日付の両方を構造体配列として格納します。

fig = uifigure;
d = uidatepicker(fig);
date = datetime("today");
fig.UserData = struct("Datepicker",d,"Today",date);

メモ

UserData プロパティは、アプリのユーザー インターフェイスに直接関連するデータの格納にのみ使用します。大規模なデータ セットやアプリ コード内で作成または変更されるデータ以外をアプリで使用する場合は、代わりにこのデータを別のファイルに格納し、そのファイルにアプリ内からアクセスします。

シンプルなアプリケーションの場合は、アプリ データを UserData プロパティに格納する代わりに、メインのアプリ関数に変数として格納し、各コールバックに入力引数または入れ子関数を使用して関連データを提供します。

コールバック関数からのアプリ データへのアクセス

コンポーネントのコールバック関数でアプリ データにアクセスするには、次のいずれかの方法を使用します。

  • UserData のデータへのアクセス — この方法は、コールバック関数内からアプリ データを更新する場合に使用します。前のセクションの説明に従って、アプリ データを UserData プロパティに格納しておく必要があります。

  • コールバックへの入力データの引き渡し — この方法は、シンプルなアプリで、コールバックがアクセスできるデータを制限する場合に使用します。コールバック コードを簡単に再利用できるようになります。

  • 入れ子にされたコールバック関数の作成 — この方法は、シンプルなアプリで、コールバック関数にすべてのアプリ データへのアクセスを提供する場合に使用します。アプリ コードを単一のファイルにまとめることができます。

以降の各セクションで、これらの方法について 1 つずつ説明し、各方法を使用してアプリ内でデータを共有する例を示します。各例の最終的なアプリの動作は同じで、アプリ ユーザーがテキスト エリアにテキストを入力し、ボタンをクリックしてテキストからワード クラウドを生成できるようにします。そのためには、アプリのテキスト エリア、ボタン、およびワード クラウドを保持するパネルでデータを共有する必要があります。このデータをそれぞれ異なる方法で共有する例を示します。

Word cloud app. The app has a text box with text, a button that says "Create Word Cloud", and a word cloud of the text in the text box.

UserData のデータへのアクセス

すべてのアプリ データを 1 か所にまとめておくには、すべてのコンポーネントから簡単にアクセスできる場所にデータを格納します。最初に、アプリ コードのセットアップ部分で、Figure ウィンドウの UserData プロパティを使用して、コンポーネントがコールバックからアクセスする必要があるすべてのデータを格納します。各 UI コンポーネントはメインの Figure の子であるため、コールバック関数内から関数 ancestor を使用して Figure にアクセスできます。たとえば、btn という名前の変数で格納されたボタンをもつパネルが Figure に含まれている場合、次のコードを使用して Figure にアクセスできます。

fig = ancestor(btn,"figure","toplevel");
コールバック内から Figure にアクセスしたら、Figure の UserData に格納されたアプリ データにアクセスして変更できます。

例: UserData を使用したワード クラウド アプリ

ワード クラウド アプリで、アプリ ユーザーがボタンをクリックしたときにアプリ データを共有するには、Figure の UserData プロパティにデータを格納します。テキスト エリアのテキストに基づいてワード クラウドをプロットする createWordCloud という名前の ButtonPushedFcn コールバック関数を定義します。関数 createWordCloud は、ボタンがクリックされたときにテキスト ボックスの値にアクセスできる必要があります。また、データをプロットするパネル コンテナーにもアクセスできる必要があります。このアクセスを提供するには、Figure の UserData をテキスト エリア コンポーネントとパネル コンテナーを格納する struct に設定します。

fig.UserData = struct("TextArea",txt,"Panel",pnl);

関数 createWordCloud で、Figure の UserData プロパティにアクセスします。MATLAB により、コールバックを実行するコンポーネントがコールバック関数に src として自動的に渡されるため、コールバック関数内から関数 ancestor を使用して Figure にアクセスできます。

fig = ancestor(src,"figure","toplevel");

その後、Figure を使用してパネルとテキストにアクセスできます。

data = fig.UserData;
txt = data.TextArea;
pnl = data.Panel;
val = txt.Value;

この例を実行するには、関数 shareUserData を MATLAB パス上の shareUserData.m という名前のファイルに保存します。

function shareUserData
  % Create figure and grid layout
  fig = uifigure;
  gl = uigridlayout(fig,[2,2]);
  gl.RowHeight = {'1x',30};
  gl.ColumnWidth = {'1x','2x'};
  
  % Create and lay out text area
  txt = uitextarea(gl);
  txt.Layout.Row = 1;
  txt.Layout.Column = 1;
  
  % Create and lay out button
  btn = uibutton(gl);
  btn.Layout.Row = 2;
  btn.Layout.Column = 1;
  btn.Text = "Create Word Cloud";
  
  % Create and lay out panel
  pnl = uipanel(gl);
  pnl.Layout.Row = [1 2];
  pnl.Layout.Column = 2;
  
  % Store data in figure
  fig.UserData = struct("TextArea",txt,"Panel",pnl);
  
  % Assign button callback function
  btn.ButtonPushedFcn = @createWordCloud;
end

% Process and plot text
function createWordCloud(src,event)
  fig = ancestor(src,"figure","toplevel");
  data = fig.UserData;
  txt = data.TextArea;
  pnl = data.Panel;
  val = txt.Value;

  words = {};
  for k = 1:length(val)
      text = strsplit(val{k});
      words = [words text];
  end
  c = categorical(words);
  wordcloud(pnl,c);
end

コールバックへの入力データの引き渡し

コールバック関数からデータにアクセスする必要がある場合、そのデータをコールバックに入力として直接渡すことができます。MATLAB によってすべてのコールバック関数に入力として自動的に渡される srcevent に加え、追加の入力引数をコールバック関数で宣言できます。それらの入力引数を cell 配列または無名関数を使用してコールバック関数に渡します。

例: コールバックの入力引数を使用したワード クラウド アプリ

ワード クラウド アプリで、アプリ ユーザーがボタンを押したときにアプリ データを共有するには、そのデータを ButtonPushedFcn コールバック関数に渡します。

テキスト エリアのテキストに基づいてワード クラウドをプロットする createWordCloud という名前の ButtonPushedFcn コールバック関数を定義します。関数 createWordCloud は、ボタンがクリックされたときにテキスト ボックスの値にアクセスできる必要があります。また、データをプロットするパネル コンテナーにもアクセスできる必要があります。このアクセスを提供するには、必須の引数である srcevent に加え、テキスト エリアとパネルを入力引数として取るように createWordCloud を定義します。

function createWordCloud(src,event,txt,pnl)
  % Code to plot the word cloud
end

createWordCloud コールバック関数を割り当て、createWordCloud へのハンドルの後に追加の入力引数を含む cell 配列として ButtonPushedFcn を指定してテキスト エリアとパネルを渡します。

btn.ButtonPushedFcn = {@createWordCloud,txt,pnl};

この例を実行するには、関数 shareAsInput を MATLAB パス上の shareAsInput.m という名前のファイルに保存します。

function shareAsInput
  % Create figure and grid layout
  fig = uifigure;
  gl = uigridlayout(fig,[2,2]);
  gl.RowHeight = {'1x',30};
  gl.ColumnWidth = {'1x','2x'};
  
  % Create and lay out text area
  txt = uitextarea(gl);
  txt.Layout.Row = 1;
  txt.Layout.Column = 1;
  
  % Create and lay out button
  btn = uibutton(gl);
  btn.Layout.Row = 2;
  btn.Layout.Column = 1;
  btn.Text = "Create Word Cloud";
  
  % Create and lay out panel
  pnl = uipanel(gl);
  pnl.Layout.Row = [1 2];
  pnl.Layout.Column = 2;
  
  % Assign button callback function
  btn.ButtonPushedFcn = {@createWordCloud,txt,pnl};
end

% Process and plot text
function createWordCloud(src,event,txt,pnl)
  val = txt.Value;
  words = {};
  for k = 1:length(val)
      text = strsplit(val{k});
      words = [words text];
  end
  c = categorical(words);
  wordcloud(pnl,c);
end

入れ子にされたコールバック関数の作成

最後に、コールバック関数をプログラム アプリのメイン関数内で入れ子にできます。こうすると、入れ子にされたコールバック関数はメイン関数とワークスペースを共有します。その結果、入れ子関数はメイン関数に定義されているすべての UI コンポーネントと変数にアクセスできるようになります。

例: 入れ子にされたコールバックを使用したワード クラウド アプリ

ワード クラウド アプリで、アプリ ユーザーがボタンを押したときにアプリ データを共有するには、ボタンのコールバック関数をメインのアプリ関数内に入れ子にします。テキスト エリアのテキストに基づいてワード クラウドをプロットする createWordCloud という名前の ButtonPushedFcn コールバック関数を定義します。関数 createWordCloud は、ボタンがクリックされたときにテキスト ボックスの値にアクセスできる必要があります。また、データをプロットするパネル コンテナーにもアクセスできる必要があります。このアクセスを提供するには、メイン関数の nestCallback 内で createWordCloud を定義します。この入れ子関数は、テキスト エリアとパネルのコンポーネントを格納する変数 tp にアクセスできます。

この例を実行するには、関数 nestCallbacknestCallback.m という名前のファイルに保存して実行します。

function nestCallback
  % Create figure and grid layout
  fig = uifigure;
  gl = uigridlayout(fig,[2,2]);
  gl.RowHeight = {'1x',30};
  gl.ColumnWidth = {'1x','2x'};
  
  % Create and lay out text area
  t = uitextarea(gl);
  t.Layout.Row = 1;
  t.Layout.Column = 1;
  
  % Create and lay out button
  b = uibutton(gl);
  b.Layout.Row = 2;
  b.Layout.Column = 1;
  b.Text = "Create Word Cloud";
  
  % Create and lay out panel
  p = uipanel(gl);
  p.Layout.Row = [1 2];
  p.Layout.Column = 2;
  
  % Assign button callback function
  b.ButtonPushedFcn = @createWordCloud;
  
  % Process and plot text
  function createWordCloud(src,event)
    val = t.Value;
    words = {};
    for k = 1:length(val)
        text = strsplit(val{k});
        words = [words text];
    end
    c = categorical(words);
    wordcloud(p,c);
  end
  
end

関連するトピック