メインコンテンツまでスキップ

チュートリアルアプリのルック&フィールをカスタマイズする

📚 Source Page

アプリケーションの基本的なウィジェットの描画をカスタマイズします。カスタムスキン独自のボタン、スライダー、その他のコンポーネントを描画することで、アプリケーションを作成できます。

レベル初心者

プラットフォーム:Windows, macOS, Linux, iOS, Android

クラス: LookAndFeel,Slider,Button,Path,AffineTransform

スタート

このチュートリアルのデモ・プロジェクトのダウンロードはこちらから:PIP|ZIP.プロジェクトを解凍し、最初のヘッダーファイルをProjucerで開く。

このステップでヘルプが必要な場合は、以下を参照してください。Tutorial: Projucer Part 1: Getting started with the Projucer.

デモ・プロジェクト

デモ・プロジェクトは、標準的なJUCEのルック&フィールを用いて、2つのボタンと2つの回転スライダを持つGUIを作成します:

標準的なルック&フィールのボタンとスライダー
標準的なルック&フィールのボタンとスライダー

についてLookAndFeelクラスは、JUCEでカスタマイズされたGUIを作成するための基本です。クラスを使ってLookAndFeelクラスでは、特定のコンポーネントのデフォルト・カラーを変更するなどの簡単なカスタマイズを行うことができます。しかし、多くの種類のコンポーネントの描画をカスタマイズすることもできます。例えば、ボタンやスライダーを独自の外観で作成することができます。

色のカスタマイズ

という場合LookAndFeelオブジェクトがコンポーネントに適用されると、そのコンポーネントに適用されます。そしてその子コンポーネント (Tutorial: Parent and child componentsただし、子コンポーネントに特別に別のルック&フィールが割り当てられている場合を除く)。

ルック・アンド・フィール・システムでできることの一つは、標準的なJUCEコンポーネントの要素に特定の色を上書きすることです(Tutorial: Colours in JUCE.)例えば、以下の行をMainContentComponentコンストラクタの両方文字盤が赤くなる:

getLookAndFeel().setColour (juce::Slider::thumbColourId, juce::Colours::red);

以下のスクリーンショットのようになるはずだ:

ルック&フィールカラーの上書き
ルック&フィールカラーの上書き

2つのダイヤルを異なるものに設定するには、新しいダイヤルを作ればいい。LookAndFeelインスタンスを追加し、それをダイヤルの片方だけに適用する。まずLookAndFeel_V4オブジェクトをメンバー[1](これはデフォルトのJUCEルックアンドフィールを実装するクラスです)。

private:
juce::LookAndFeel_V4 otherLookAndFeel; // [1]
juce::Slider dial1;
juce::Slider dial2;
juce::TextButton button1;
juce::TextButton button2;

次に、先ほど追加したコンストラクタのコード行を次のように変更する:

otherLookAndFeel.setColour (juce::Slider::thumbColourId, juce::Colours::red);

このルック&フィールを使ってみようのみを最初のダイヤルに追加する。このコード行をMainContentComponentビルダー

        dial1.setLookAndFeel (&otherLookAndFeel);

これで、以下のスクリーンショットのようなUIが作成されるはずだ:

コンポーネントごとに異なるルック&フィール・オブジェクトを使用する
コンポーネントごとに異なるルック&フィール・オブジェクトを使用する

もちろん、この単純な例では、この方法はSlider::thumbColourId色をスライダーオブジェクトに直接適用することができます。しかし、アプリでは複数のスライダーを異なる目的で使用することがあり、ある目的のスライダーには1つのカラーセットを使用し、他の目的のスライダーには異なるカラーセットを使用したい場合があります。このアプローチでは、各スライダーにそのタイプに適したルック&フィールが割り当てられている限り、これらの色をグローバルに変更することができます。

このアプローチの利点は、実際の描画コードをカスタマイズし始めるとはっきりする。特に、カスタム・ルック&フィール・クラスを作成する必要がある。

カスタム・ルック&フィール

特定のコンポーネントの描画をカスタマイズするためには、以下のクラスを継承した新しいクラスを作成する必要がある。LookAndFeelクラスを継承しています。もしLookAndFeelクラスを実装する必要がある。すべて純粋仮想関数のこれらの関数がすでに定義されているクラスを継承する方がはるかに現実的だ。必要なものだけをオーバーライドすればいい。デフォルトのルック&フィールと比較して、この1つの色の変更だけが定義されたシンプルなカスタム・ルック&フィールを作成してみましょう。

まず、先ほど追加したコンストラクタからこの行を削除する:

otherLookAndFeel.setColour (juce::Slider::thumbColourId, juce::Colours::red);

さて、新しいクラスを追加します。LookAndFeel_V4クラスの前にMainContentComponentクラスである:

class OtherLookAndFeel : public juce::LookAndFeel_V4
{
public:
OtherLookAndFeel()
{
setColour (juce::Slider::thumbColourId, juce::Colours::red);
}

このコードを実行する前に、クラス名を変更します。otherLookAndFeelOtherLookAndFeelのメンバー[2]:

private:
OtherLookAndFeel otherLookAndFeel; // [2]
juce::Slider dial1;
juce::Slider dial2;
juce::TextButton button1;
juce::TextButton button2;

アプリケーションをビルドして実行すると、前のスクリーンショットと同じ結果が表示されるはずです。

図面のカスタマイズ

には多くの機能がある。LookAndFeelクラスは、さまざまなタイプのコンポーネントに対応している。特定のコンポーネント・タイプに指定された関数は、すべてLookAndFeelMethods関連するコンポーネント・クラス内の

スライダーのカスタマイズ

例えばSlider::LookAndFeelMethodsJUCE API ドキュメントの中にあります。このリストの中にSlider::LookAndFeelMethods::drawRotarySlider().

これをOtherLookAndFeelクラスに追加する。宣言文をクラスに追加する:

    void drawRotarySlider (juce::Graphics& g, int x, int y, int width, int height, float sliderPos,
const float rotaryStartAngle, const float rotaryEndAngle, juce::Slider&) override

ここでは、以下のデータが渡されていることがわかる:

  • g(その)Graphicsという文脈がある
  • x回転スライダーを描く矩形の左上のx座標
  • y回転スライダーを描く矩形の左上のy座標
  • width回転スライダーを描く矩形の幅
  • height回転スライダーを描く矩形の高さ
  • sliderPos:その位置これはスライダーの実際の値の範囲とは無関係です)
  • rotaryStartAngle文字盤の回転開始角度(ラジアン単位)
  • rotaryEndAngle文字盤の回転終了角度(ラジアン単位)
  • slider:そのSliderオブジェクトそのものである
注記

x、y、width、heightの引数は、すべてのテキストボックススライダーが使用しているかもしれないそのため、スライダーの位置とサイズにアクセスし、それらの値を使用することができます。

それでは、文字盤の指針を表す線と塗りつぶされた円だけのシンプルな文字盤を描くように、関数本体を書いてみましょう。まず、渡された値に基づいて計算するために、いくつかの一時変数が必要です:

        auto radius = (float) juce::jmin (width / 2, height / 2) - 4.0f;
auto centreX = (float) x + (float) width * 0.5f;
auto centreY = (float) y + (float) height * 0.5f;
auto rx = centreX - radius;
auto ry = centreY - radius;
auto rw = radius * 2.0f;
auto angle = rotaryStartAngle + sliderPos * (rotaryEndAngle - rotaryStartAngle);
注記

最終的にangle変数には文字盤が指すべき角度が格納される。

次に、文字盤の色を塗りつぶし、輪郭を描くコードを追加しよう:

        // fill
g.setColour (juce::Colours::orange);
g.fillEllipse (rx, ry, rw, rw);

// outline
g.setColour (juce::Colours::red);
g.drawEllipse (rx, ry, rw, rw, 1.0f);

ポインターそのものを描画するために、最初にPathオブジェクトを平行移動させ、必要な角度だけ回転させる:

        juce::Path p;
auto pointerLength = radius * 0.33f;
auto pointerThickness = 2.0f;
p.addRectangle (-pointerThickness * 0.5f, -radius, pointerThickness, pointerLength);
p.applyTransform (juce::AffineTransform::rotation (angle).translated (centreX, centreY));

そして、このパスを埋めてポインターを描画する:

        // pointer
g.setColour (juce::Colours::yellow);
g.fillPath (p);
注記

このセクションの完成したコードはLookAndFeelCustomisationTutorial_02.hファイルを参照してください。

エクササイズ

ポインタの描画を変更します。長さを変えてみたり、少し太いけれど丸みを帯びた長方形にしてみたり、矢印を描いてみたり。

の1つをシンプルにカスタマイズしたものです。Sliderルック・アンド・フィールのメソッド。しかし、この原則は他のメソッドにも当てはまる。おそらく、他のカスタマイズを作成するための最良のアプローチは、既存の実装をLookAndFeel_V4またはLookAndFeel_V3クラスを作成し、これを自分のコードの基礎として使用する。

注記

についてLookAndFeel_V4クラスはLookAndFeel_V3クラスで再定義されないメソッドもある。LookAndFeel_V4クラスである。

ボタンのカスタマイズ

ボタンのカスタマイズを見てみましょう。まずOtherLookAndFeelクラスのルック&フィールである。MainContentComponentこの行をコンストラクタで使用する:

        setLookAndFeel (&otherLookAndFeel);

またLookAndFeelオブジェクトは、シャットダウン時にMainContentComponentこの行をデストラクタに指定することで、もうその行はない:

    ~MainContentComponent() override
{
setLookAndFeel (nullptr);
}

これはもちろん、両方の文字盤が前のセクションでカスタマイズした外観になることを意味します。次にButton::LookAndFeelMethods::drawButtonBackground()関数宣言:

    void drawButtonBackground (juce::Graphics& g, juce::Button& button, const juce::Colour& backgroundColour,
bool, bool isButtonDown) override

ここでは、以下のデータが渡される:

  • g(その)Graphicsという文脈がある。
  • button(その)Buttonオブジェクトそのものである。
  • backgroundColour使用されるべき背景色(これはLookAndFeelボタンのトグル状態に応じた色)。
  • isMouseOverButtonマウスポインタがボタンの範囲内にあるかどうか。
  • isButtonDownマウスボタンが押されているかどうか。

では、ボタンの矩形を背景色で塗りつぶすだけの、とてもシンプルなボタン背景を作るために、関数本体を追加してみましょう:

auto buttonArea = button.getLocalBounds();
g.setColour (backgroundColour);
g.fillRect (buttonArea);
buttonfloat float UnityEventModifiers int buttonDefinition juce_UnityPluginInterface.h:200

これをビルドして実行すると、以下のスクリーンショットのようになるはずだ:

シンプルなボタン
シンプルなボタン

これを操作すると、ボタンがマウス・ポインターの操作に視覚的に反応しないことに気づくだろう。簡単なシャドウ効果を実装してみましょう。ボタンを変更するdrawButtonBackground()関数をこれに追加する:

        auto buttonArea = button.getLocalBounds();
auto edge = 4;

buttonArea.removeFromLeft (edge);
buttonArea.removeFromTop (edge);

// shadow
g.setColour (juce::Colours::darkgrey.withAlpha (0.5f));
g.fillRect (buttonArea);

auto offset = isButtonDown ? -edge / 2 : -edge;
buttonArea.translate (offset, offset);

g.setColour (backgroundColour);
g.fillRect (buttonArea);

これで、ボタンをクリックするとボタンが動いて見えるようになった。残念なことに、テキストは静止したままである。Button::LookAndFeelMethods::drawButtonText()関数を使うことで、より信憑性を高めることができる。この関数を書くために、まずはLookAndFeel_V2クラスを作成し、それをOtherLookAndFeelクラスに追加する:

void drawButtonText (juce::Graphics& g, juce::TextButton& button, bool isMouseOverButton, bool isButtonDown) override
{
auto font = getTextButtonFont (button, button.getHeight());
g.setFont (font);
g.setColour (button.findColour (button.getToggleState() ? juce::TextButton::textColourOnId
: juce::TextButton::textColourOffId)
.withMultipliedAlpha (button.isEnabled() ? 1.0f : 0.5f));

auto yIndent = juce::jmin (4, button.proportionOfHeight (0.3f));
auto cornerSize = juce::jmin (button.getHeight(), button.getWidth()) / 2;

auto fontHeight = juce::roundToInt (font.getHeight() * 0.6f);
auto leftIndent = juce::jmin (fontHeight, 2 + cornerSize / (button.isConnectedOnLeft() ? 4 : 2));
auto rightIndent = juce::jmin (fontHeight, 2 + cornerSize / (button.isConnectedOnRight() ? 4 : 2));
auto textWidth = button.getWidth() - leftIndent - rightIndent;

if (textWidth > 0)
g.drawFittedText (button.getButtonText(),
leftIndent, yIndent, textWidth, button.getHeight() - yIndent * 2,
juce::Justification::centred, 2);
}
TextButtonA button that uses the standard lozenge-shaped background with a line of text on it.Definition juce_TextButton.h:51
juceDefinition juce_AudioWorkgroup_mac.h:36

テキストが描画されるオフセットを変更するだけでよい。drawButtonBackground()関数を変更する必要があります。最後の数行だけを変更する必要がある:

        auto textWidth = button.getWidth() - leftIndent - rightIndent;

auto edge = 4;
auto offset = isButtonDown ? edge / 2 : 0;

if (textWidth > 0)
g.drawFittedText (button.getButtonText(),
leftIndent + offset, yIndent + offset, textWidth, button.getHeight() - yIndent * 2 - edge,
juce::Justification::centred, 2);
}

これをビルドして実行すると、以下のスクリーンショットのようになるはずだ。

影のあるボタン(ボタン1は "クリックされた"と表示される)
影のあるボタン(ボタン1は "クリックされた"と表示される)
注記

このセクションの完成したコードはLookAndFeelCustomisationTutorial_03.hファイルを参照してください。

エクササイズ

マウスポインタがボタンの上に来たときに反応するように、ボタンの描画に変更を加えます。例えば、背景色を少し調整したり、影の色を変えたり、矩形のサイズや位置を微妙に変えたりすることができます。

概要

このチュートリアルでは、JUCEコンポーネントのルック&フィールをカスタマイズする概念を紹介しました。LookAndFeelクラスで使用されます。特に以下のことができるようになるはずだ:

  • デフォルトのルック&フィールで色をカスタマイズ。
  • 新しいルック&フィールのクラスを作る。
  • スライダーとボタンの描画コードをカスタマイズ
  • JUCEコンポーネントをカスタマイズできるように、他のコンポーネントのルック&フィールのメソッドを検索します。

こちらも参照