bio_img_japan-community

MATLAB ユーザーコミュニティー

MATLAB & Simulink ユーザーコミュニティー向け日本語ブログ

グラフ作成とアプリ開発のための”テーマ”ガイド

※この投稿は 2025 年 7 月 22 日に MATLAB Graphics and App Building へ 投稿されたものの抄訳です。
待望のダークテーマが MATLAB R2025a で利用できるようになりました。この記事は、特定のテーマでグラフやアプリをデザインしたり、どちらのテーマにも自動的に適応するようにするためのガイドです。デフォルトでは、グラフィックステーマはデスクトップテーマと一致するため、グラフやアプリはシステム設定に応じてダークテーマまたはライトテーマで表示されます。これらの設定は、MATLAB 設定ダイアログで調整できます
テーマが選択できる状態では色の選択は重要になります。ライトテーマでは目立つ色が、ダークテーマでは見づらい場合があります。この課題に対処するため、MATLAB グラフィックスのデフォルトのカラーシステムは、テーマ間で色のコントラストを維持しながら自動的に調整されるように設計されています。ただし、手動で設定された色は意図的なデザイン選択として扱われ、テーマの変更には適応されません。
この記事では、テーマが選択できる環境における色選択の戦略について解説します。特定のテーマに合わせたグラフィカルコンテンツのデザイン手順や、グラフやアプリをテーマに合わせてカスタマイズする手順も含まれています。MATLAB におけるテーマのより広範な概要については、Abby Skofieldの最近の記事「Dark Theme for Plots and Apps」をご覧ください。

1. 色プロパティがテーマにどのように対応するかを理解する

デフォルトの色は Figure の現在のテーマに合わせて調整されます

手動で設定されていない色プロパティはデフォルト値を使用します。例えば、h=plot(magic(3)) は、軸の ColorOrder プロパティで定義された色で 3 本の線を生成します。これらの線オブジェクトの ColorMode プロパティは「auto」であり、これはオブジェクトにデフォルトの色が割り当てられていることを示します。MATLAB テーマの重要な機能として、デフォルトの色は図のテーマに応じて自動的に更新されます。
明るいテーマと暗いテーマに適応するデフォルトの色を使用した図

手動で設定された色は Figure のテーマ変更の影響を受けません

色プロパティを手動で設定すると、デフォルトの色値が使用されなくなり、図のテーマに適応しなくなります。たとえば、h=plot([2 5 4],’-k’) は黒い線を生成し、その線の ColorMode プロパティは ‘manual’ です。手動で設定された色は意図的なデザイン上の選択であるとみなされ、Figure のテーマによって影響を受けません。この線がダーク テーマで生成された場合、線と軸の背景の色のコントラストが大幅に低下し、線がほとんど見えなくなります。以下の例では、ライト テーマ (左) では緑の線が「成功」というラベルの付いたデータを強調表示し、灰色を使用して「失敗」というラベルの付いたデータを強調表示していません。これらの色は手動で設定されたため、ダーク テーマを適用しても保持されます (右)。ただし、ダーク テーマでは、灰色の「失敗」データが強調表示される一方で緑の「成功」データは見づらいため、フォーカスが逆転します。
ライトテーマで選択した色をダークテーマで見た場合

カラーマップとトゥルーカラー配列はテーマの影響を受けません

カラーマップ(例:サーフェス、等高線)またはトゥルーカラー配列(例:画像、アイコン)によって決定される色は、グラフィックテーマの影響を受けません。ただし、このルールの例外として、ライトテーマではデフォルトで sky カラーマップ、ダークテーマでは abyss カラーマップを使用する一部のグラフ(例:ヒートマップ、ビンスキャッター)があります。

2.テーマが設定できる環境で図やアプリをデザインする

R2025a のグラフィックテーマは、デフォルトで MATLAB デスクトップテーマに合わせて設定されています。このデスクトップテーマは、システムのテーマに合わせて設定されています。デスクトップとグラフィックテーマのデフォルトは、設定パネルで変更できます(Dark Theme for Plots and Apps を参照)。MATLAB のインストール環境によって設定が異なる場合があるため、同じ図やアプリでも異なるテーマで表示されることがあります。ここでは、テーマが設定できる環境で図をデザインするための 3 つの推奨戦略を紹介します。
  1. 手動で設定した色をデフォルトの色に戻す
  2. 設定に左右されない特定のテーマのチャートをデザインする
  3. テーマが変更されたときに手動で設定した色を更新する図を設計する

戦略1: 手動で設定した色をデフォルトの色に戻す

色を設定する必要がない場合は、この戦略を使用します。
データ可視化において、色は意味、知覚的なグループ分け、ブランディング、そして美的感覚を伝えるためによく用いられます。しかし、習慣や必要性のなさ、あるいは場当たり的なコピー&ペーストの結果として、手動で色を割り当ててしまうことがあります。このような場合、コードから不要な色割り当てを見つけて削除するのが最善策です。色割り当てを削除することで、色プロパティはデフォルトの色値に戻り、図のテーマに適合するようになります。
手動で割り当てた色を見つけるには、位置指定の入力引数、名前と値のペア、またはグラフィックオブジェクトのプロパティ設定で色定義を探します。それらの色定義を削除するだけです。以下の表は、一般的な色割り当てパターンとその削除方法を示しています。
色の手動設定例
デフォルト色を使用する例
text(x, y, string, ‘Color’, ‘k’)
text(x, y, string)
figure(Color=‘white’)
figure()
bar(y,‘blue’)
bar(y)
plot(x,y,‘–k’)
plot(x,y,‘–‘)
scatter(x,y,size,‘black’,‘filled’,‘diamond’)
scatter(x,y,size,‘filled’,‘diamond’)
set(h,‘Color’,[r g b])
<delete>
h.MarkerFaceColor = [r g b];
<delete>
h1.Color = h2.Color;
h1.SeriesIndex = h2.SeriesIndex;
*Not all objects have a SeriesIndex property
ヒント: 色プロパティが設定されている場所がわからない場合は、オブジェクトの作成後に以下のリスナーを呼び出してください。色プロパティが変更されると、色プロパティが設定された場所を示す警告が表示されます。h をオブジェクトハンドルを含む変数に、Color を色プロパティ名に置き換えてください。この例では、オブジェクト hColor プロパティは「demo」というスクリプトの102行目で設定されています。
>> addlistener(h,‘Color’,‘PreSet’,@(~,~)warning(‘Color value set.’));
Warning: Color value set.
> In demo>@(~,~)warning(‘Color value set.’)
In demo (line 102)

戦略2: 設定に左右されない特定のテーマに合わせた図やアプリをデザインする

ライトテーマまたはダークテーマ向けに設計する場合は、この戦略を使用します。
図やアプリを特定のテーマで表示したい場合は、Figure のテーマプロパティを明示的に設定してください。これにより、グラフィックテーマの設定がオーバーライドされ、図は常に設計どおりに表示されます。例えば、R2025a より前に作成されたグラフの外観を維持するには、図のテーマを light に設定します。App Designer では、コンポーネントブラウザまたはアプリのスタートアップ関数でプログラム的に Figure のテーマプロパティを設定します。
テーマ設定方法例
figure(Theme=“light”)
theme(fig, “dark”)
fig.Theme = “light”;
set(fig, “Theme”, “dark”)
ヒント: R2025a より前の MATLAB リリースとの互換性を維持するには、現在の MATLAB リリースに基づいて Theme プロパティを条件付きで設定してください。isMATLABReleaseOlderThan (R2020b 以降) または verLessThan を参照してください。
fig = figure();
if ~verLessThan(“matlab”,“25.0”) % R2025a
    theme(fig, “light”)
end

戦略3: テーマが変更されたときに手動で設定した色を更新する図とアプリを設計する

この戦略は、手動で割り当てられた色を使用しながら、図やアプリがライトテーマとダークテーマの両方で視覚的に効果的でアクセシビリティを維持する必要がある場合を想定しています。これは、テーマの変更時に色の値をプログラムで更新することで実現されます。
チャートまたはアプリの構築方法に応じて、主に 2 つのアプローチがあります。
  1. スクリプト内のグラフィックまたは UI オブジェクトのコレクションとして作成されたグラフやアプリ、または App Designer で作成されたアプリの場合は、Figure の ThemeChangedFcn コールバックを使用して、テーマの変更に応じて色を更新します。
  2. ChartContainer を使用して構築されたカスタム チャート クラスまたは ComponentContainer を使用して作成されたカスタム UI コンポーネントの場合は、コンテナーの update メソッド内で getTheme メソッドを使用して、各テーマの色を設定します。
次のセクションでは、各アプローチの推奨ワークフローについて説明します。

ThemeChangedFcn : グラフィック オブジェクトから作成された図やアプリ、および App Designer で作成された図やアプリ用

ThemeChangedFcn はR2025a で Figure オブジェクトに導入されたコールバック関数です。このコールバックは、Figure のテーマが変更されたときに呼び出されます。グラフィックス オブジェクトのプロパティ値は、現在のテーマに応じてコールバック関数内で更新できます。MATLAB は、2 つの入力引数を ThemeChangedData に自動的に渡します。1 つ目は Figure のハンドル、2 つ目はコールバック イベントによって生成された ThemeChangedData オブジェクトです。Figure と ThemeChangedData オブジェクトの両方の Theme プロパティは、 GraphicsTheme オブジェクトを返します。GraphicsTheme オブジェクトには、Figure の現在のテーマを ‘dark’ または ‘light’ として示す BaseColorStyle プロパティが含まれています。Figure の以前のテーマも ThemeChangedData で参照できます。これらのオブジェクトの内容を以下に示します。
GraphicsTheme および ThemeChangedData オブジェクトのスクリーンショット
現在のテーマが識別されると、コールバック内でプロパティ値を条件付きで更新し、任意のテーマにおける手動による色割り当てを制御できます。以下の例では、ニュートンの冷却の法則を描いたプロットに ThemeChangedFcn を適用しています。関数の交換と可読性を容易にするために、オブジェクトハンドルは構造体に格納されています。この構造体は ThemeChangedFcn に渡され、現在の図のテーマに従って色が適用されます(完全なファイル:NewtonsLawOfCoolingDemo.mを参照)。
% Create graphics objects
fig = figure();
hold on;
h = struct(); % Used to store graphics handles
h.coolingCurve = plot(__, ‘-‘, LineWidth=2);
h.thresholdLine = yline(__, ‘–‘, LineWidth=2);
h.safeHandlingPoint = plot(__, ‘o’, MarkerSize=8);
% Define ThemeChangedFcn
fig.ThemeChangedFcn = @(fig,data)updateManualColors(fig, data, h);
updateManualColors(fig,[],h) % initialize using the current figure theme
function updateManualColors(fig,~,h)
% ThemeChangedFcn: invoked when the theme changes.
if fig.Theme.BaseColorStyle == “dark”
    % Dark theme colors
    h.coolingCurve.Color = [0.6 0.7 1]; % lighter blue
    h.thresholdLine.Color = [1 0.2 0.2]; % lighter red
    h.safeHandlingPoint.MarkerFaceColor = [0 .6 0]; % darker green
    h.safeHandlingPoint.MarkerEdgeColor = [0.5 0.8 0.5]; % lighter green
else
    % Light theme colors
    h.coolingCurve.Color = [0 0 1]; % blue
    h.thresholdLine.Color = [1 0 0]; % red
    h.safeHandlingPoint.MarkerFaceColor = [0 1 0]; % green
    h.safeHandlingPoint.MarkerEdgeColor = [0 0.4 0]; % dark green
end
end
ライトテーマとダークテーマで表示される色は以下の通りです。
ThemeChangedFcn を使ってライトテーマとダークテーマそれぞれで設定された色
カラーマップ (sky, abyss など)、画像、アイコンなど、テーマ変更によって変わらないその他のプロパティも、コールバック内で更新できます。

ThemeChangedFcn を使用した図またはアプリの初期化

ThemeChangedFcn は、Figure のテーマが変更された場合にのみ呼び出されます。Figure がデフォルトのテーマで初期化された場合、ThemeChangedFcn は呼び出されないため、 ThemeChangedFcn 内の色の割り当ては実行されません。ThemeChangedFcn で定義された手動で設定された色でフィギュアが初期化されるようにするには、2つの方法があります。
  1. ThemeChangedFcn を直接呼び出すThemeChangedFcn には、Figure のハンドルと ThemeChangedFcn という2つの必須入力引数があり、どちらも Figure の現在のテーマへのアクセスを提供します。コールバック関数が ThemeChangedFcn を使用しない場合は、図のセットアップ時またはアプリの startup 関数内からこの関数を直接呼び出すことができます。これは、上記の ThemeChangedFcn デモで示されています。updateManualColors(fig,[],__)
  2. ThemeChangedFcn をトリガーするThemeChangedData が必要な場合に使用します。セットアップ中またはアプリの startup 関数内で、Figure のテーマを変更し、Figure の ThemeChangedFcn を定義し、クリーンアップオブジェクトを使用してフィギュアのThemeModeを「auto」に戻します。セットアップが完了する直前に、クリーンアップオブジェクトは一時的なテーマ変更を元に戻し、ThemeChangedFcn をトリガーします。セットアップメソッドでは、以下のように記述します。
% revert theme to auto and trigger ThemeChangedFcn upon exiting setup
returnInitialTheme = onCleanup(@() theme(fig, “auto”));
% temporary theme change
initialTheme = fig.Theme;
if initialTheme.BaseColorStyle == “dark”
    theme(fig, “light”)
else
    theme(fig, “dark”)
end
% define ThemeChangedFcn
fig.ThemeChangedFcn = @updateManualColors;

getTheme: ChartContainer を使用して作成されたクラスと ComponentContainer を使用して作成された UI コンポーネントの場合

matlab.graphics.chartcontainer.ChartContainer クラスと matlab.ui.componentcontainer.ComponentContainer クラスは、高度なチャートオブジェクトとカスタム UI コンポーネントを作成するために使用されます。これらのコンテナクラスは、図のテーマが変更されたときに呼び出される update メソッドを提供します。そのため、ChartContainer や ComponentContainer から派生したクラスを使用する場合は、ThemeChangedFcn コールバックを使用する必要はありません。代わりに、 update メソッド内で getTheme メソッドを使用して、Figure の GraphicsTheme オブジェクトを取得します。前のセクションで説明したように、GraphicsTheme オブジェクトには、チャートの現在のテーマを示す BaseColorStyle プロパティが含まれています。update メソッドは、setupメソッドの後に呼び出され、初期化時およびその後のテーマ変更時にカラー管理を可能にします。
以下のメソッドブロックには、ライトテーマとダークテーマの両方をサポートする surface、line、および scatter オブジェクトのカラーマネジメントを示すために作成した SphericalLissajousCurve クラスの setup メソッドと update メソッドのスニペットが含まれています(完全なファイル: SphericalLissajousCurve.mを参照)。球面リサジュー曲線は球面上を均一かつ対称的にカバーするため、衛星スキャンや軌道力学など、ダークテーマが役立つ分野で使用されます。
  • setup メソッドは、surface、line、および scatter オブジェクトを初期化し、線の幅や透明度など、テーマに依存しないプロパティを設定します。
  • updateメソッドは、現在のテーマに基づいて色の割り当てを管理するヘルパー関数 updateColor を呼び出します。
  • 2 セットのカラーが定義されています。1 つはライト テーマ用、もう 1 つはダーク テーマ用です。
methods(Access = protected)
function setup(obj)
% …
obj.SphereSurf = surf(___, FaceAlpha=0.4, EdgeAlpha=0.3);
obj.LissajousCurve = plot3(___, LineWidth=2);
obj.IntersectionPoints = scatter3(___, MarkerEdgeColor=“none”);
end
function update(obj)
% …
updateColor(obj);
end
function updateColor(obj)
thm = getTheme(obj);
switch thm.BaseColorStyle
    case “light”
        obj.SphereSurf.FaceColor = [0.4 0.4 0.4]; % darker gray
        obj.LissajousCurve.Color = [0.53 0.80 0.92]; % sky blue
        obj.IntersectionPoints.MarkerFaceColor = [0 0 0.5]; % Navy blue
    case “dark”
        obj.SphereSurf.FaceColor = [0.67 0.67 0.67]; % lighter gray
        obj.LissajousCurve.Color = [0 0.3 0.43]; % dark blue
        obj.IntersectionPoints.MarkerFaceColor = [0.8 0.87 1]; % light blue
end
end
リサージュ曲線は、m1 と m2 で定義される高調波周波数と、アルファで定義される位相回転によって生成されます。デフォルトのグラフィックテーマはライトなので、セットアップ時にはライトテーマで選択した色が適用されます。チャート作成後にダークテーマを適用すると、チャートの更新メソッドが呼び出され、sphere、line、scatter の各オブジェクトにダークテーマで選択した色が割り当てられます。
S = SphericalLissajousCurve(m1=6, m2=7, alpha=0.07)
theme dark
各テーマの update メソッドで手動で設定された色

 

3. 色の組み合わせを選ぶ

ライトテーマとダークテーマに効果的なカラーペアを選択するのは難しい場合があります。R2025aでは、fliplightness 関数が導入されました。この関数は、RGBトリプレット、つまり色相を維持しながら明度を反転することで色配列を変換します。例えば、濃い青は薄い青に、薄い緑は濃い緑になります。下の左側のロゴは TrueColor配列で、fliplightness を使用して右側のバージョンに変換されました。
オリジナルのロゴ(左)、fliplightness を使用して変換(右)

Additional resources

 

|
  • print

Comments

To leave a comment, please click here to sign in to your MathWorks Account or create a new one.