JUCEプログラミング、Colors in JUCE、デモアプリ実装と内容

色の扱いは見た目を整えるうえでも大切ですね。

基本的なことだけど、しっかり勉強していこう~

JUCEチュートリアル、「Interface Design」の「Colours in JUCE」チュートリアルを進めていきます。このチュートリアルでは、JUCEの色の扱いを勉強するようです。まずは色を勉強するためのGUIを含んだデモアプリを実装していきます。この記事では、「Colours and general painting operations」の項目までカバーしています。

公式のチュートリアルページはこちらになります。

目次

こんな人の役に立つかも

・JUCEプログラミングを勉強している人

・JUCEチュートリアル「Colors in JUCE」をやっている人

・Colors in JUCEのデモアプリを実装している人

デモアプリ

チュートリアルからダウンロードできるプログラム「ColoursTutorial_01.h」をProjucerのテンプレートから生成されるヘッダーファイルとCPPファイルの構成で動作するものを実装していきます。

次のようないくつかのGUIコンポーネントが並んだようなデモアプリを実装してチュートリアルを進めていきます。

プロジェクトの作成

Projucerの「GUI」テンプレートからデモアプリを実装していきます。

今回はプロジェクト名を「ColorsTutorial01としました。

実装とその内容

Projucerで生成したGUIの枠に、デモアプリの実装を行っていきます。

MainComponent.h

テンプレートから作成したMainComponent.hファイルに、以下のようなprivateなメンバを追加します。

class MainComponent  : public juce::Component
{
public:
//...略...
private:


    //privateなメンバを追加します。
    juce::Label label{ {}, "This is some label text." };//[1]
    juce::TextButton textButton{ "This is a button" };//[2]
    juce::TextEditor textEditor;//[3]
    juce::Slider slider1;//[4]
    juce::Slider slider2;//[5]

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)
};

privateなメンバは、それぞれ次のようなGUIのコンポーネントのオブジェクトとなります。

LabelとTextButton、こんな風に初期値を与えられるんですね~。

MainComponent.cpp

コンストラクタ

cppファイルの最初に定義されている初期化を扱うコンストラクタの内容を以下のように書き換えます。

MainComponent::MainComponent()
{

    //[1]ラベルの初期化です。
    label.setEditable(true);
    addAndMakeVisible(label);

    //[2]テキストエディタの初期化です。
    textEditor.setText("This is a text editor.");
    addAndMakeVisible(textEditor);

    //[3]ボタンの初期化です。
    textButton.setClickingTogglesState(true);
    addAndMakeVisible(textButton);

    //[4]スライダーの初期化です。
    addAndMakeVisible(slider1);
    addAndMakeVisible(slider2);

    //[5]ウィンドウサイズを指定します。
    setSize(600, 210);
}

[1]では、ラベルの初期化を行っています。setEditable関数にtureを与えると、編集可能になります。

AddAndMakeVisibleは、コンポーネントを可視化しています。可視化しないとウィンドウに表示されないので要注意です。

[2]では、テキストエディタの初期化を行います。setText関数でエディタないの初期の文字列を指定しています。先ほどの編集可能ラベルとの違いは、背景に枠が歩かないかぐらいだと思うのですが、一応、違うクラスということで配置しておきます。ラベルと同じようにAddAndMakeVisibleで可視化を行います。

[3]では、テキストボタンの初期化を行っています。テキストボタンのテキストは、ヘッダで定義したときに定義しています。setClickingTogglesState関数をTrueとすることで、ボタンの性質がトグルボタンになります。一回押したらONの状態が保持されて、もう一回押すとOFFの状態が保持される、というチェックボックスのような性質のボタンです。

[4]では、2つのスライダーを初期化します。スライダーの詳細な設定はせず、デフォルトのままで、AdAndMakeVisibleで可視化だけを行っています。

paint関数

paint関数は、GUIの描画を行う関数です。一定間隔でコンポーネント(このPaint関数はMainComponentクラスのpaintなので、MainComponentクラスのGUI描画)の描画を行っています。

void MainComponent::paint (juce::Graphics& g)
{
    g.fillAll(juce::Colours::lightgreen);//[1]背景の塗りつぶしです。
    g.setColour(juce::Colours::orange);//[2]これ以降の描画色をオレンジに設定します。

    //[3]オレンジの外枠線の描画です。
    auto centralArea = getLocalBounds().toFloat().reduced(10.0f);
    g.drawRoundedRectangle(centralArea, 5.0f, 3.0f);

    //[4]juce::Colourクラスの配列を作成します。
    juce::Array<juce::Colour> colours{ juce::Colours::red, juce::Colours::green, juce::Colours::blue };

    //[5]色の描画領域を取得します。
    auto colourBarArea = centralArea.reduced(4.0f).withHeight(20.0f);
    auto colourArea = colourBarArea.withWidth(colourBarArea.getWidth() / (float)colours.size());

    //[6]color配列の数分範囲forで回します。
    for (auto colour : colours)
    {
        g.setColour(colour);
        g.fillRect(colourArea);

        colourArea.translate(colourArea.getWidth(), 0.0f);
    }
}

[1]では、graphicsクラスのfillAll関数でコンポーネントの全体を塗りつぶします。「juce::Colours::lightgreen」とすることで、色名で色を指定しています。

[2]では、これ以降の描画色をオレンジに設定しています。(チュートリアルによると、描画コンテキストの色設定、というような表現です。)このあとでgrafichsクラスの関数で描画するテキストや線などは、この色で描画されます。色を変更するときは、再度setColour関数で指定します。

[3]で、ウィンドウの一番外のオレンジの枠を描画しています。

まずは、「centralArea」変数に、rectangleクラスのオブジェクトとして、矩形領域を取得します。rectangleクラスは、原点X,Yと矩形の幅、高さのパラメータをまとめた便利なクラスです。まず、getLocalBounds関数は、MainComponent関数の領域のrectangleオブジェクトを返す関数です。それに続くtoFloat関数は、rectangleクラスの関数で、返すrectangleオブジェクトの値をfloat型にキャストするものです。さらに、それに続くreduced関数もrectangleクラスの関数で、引数に与えた数値分、縮小したrectangleオブジェクトを返すものです。最終的に「centralArea」には、MainComponentの描画領域から上下左右に10.0fの余白をとったrectangleオブジェクトが格納されることになります。

[4]~[6]では、ウィンドウ上部の色が並んでいる部分を描画する処理です。

[4]で、juce::Colourクラスを3つ格納するjuce::Arrayを作成しています。JUCEのクラスを配列として並べているだけです。格納する要素として、red、green、blueとしています。

[5]では、先ほどオレンジ枠の描画に利用したrectangle、「centralArea」を4.0f小さくしたrectangleをreduce関数で取得しています。続けて、rectangleクラスの関数、withHeight関数の引数に20.0fを与えると、高さだけ指定したものに更新したrectangleオブジェクトを取得できます。「colourBarArea」には、オレンジ枠から4.0f縮小かつ、高さが20.0の矩形領域が得られます。これは、赤、緑、青の矩形全体の領域になります。

そして、colourAreaとして、幅をcolor配列の数で割った値をwithWidth関数(幅だけ違う矩形領域を取得)で取得することで、「colourArea」変数に先ほどのGUIの赤の矩形領域を格納しています。

最後の[6]では、[4]と[5]で準備した情報をもとに、GUIに矩形を描画します。

colour配列(juce::Array)の要素数分、範囲for分で繰り返すことで3つの矩形を描画します。setColor関数で色を指定、引数には、color配列の要素を当てはめるので、繰り返す毎に赤、緑、青と変化していきます。fillRectは矩形を描画する関数です。ここに引数として、[5]で作成したcolourAreaを与えます。そして、colourAreaの位置を右にずらすためにtranslate関数を使用します。translate関数は、引数に与えたX,Y方向に矩形を移動させるものです。colourArea自身の矩形位置情報を更新する関数です。類似関数に、移動した矩形を返す関数translatedもありますが、今回はcolourArea自身の値を更新するので、translate関数を使っています。

描画処理、イメージできないと意外とつらいかもしれません。

resize関数

最後にresized関数でコンポーネントをGUI上に配置します。resized関数はウィンドウのサイズ変更時にも実行されて、基本的にこの関数内で、ウィンドウ上のコンポーネントを配置していきます。

void MainComponent::resized()
{
    label.setBounds(20, 40, getWidth() - 40, 20);
    textEditor.setBounds(20, 70, getWidth() - 40, 20);
    textButton.setBounds(20, 100, getWidth() - 40, 20);
    slider1.setBounds(20, 130, getWidth() - 40, 20);
    slider2.setBounds(20, 160, getWidth() - 40, 20);
}

setBounds関数は、コンポーネントの位置と大きさを指定する関数で、引数にX、Y、幅、高さを与えます。(rectangleを引数とするものもあります。)今回は、この関数でウィンドウ上にコンポーネントを配置していきます。

すべてのコンポーネントで違うところは、配置原点のYの位置のみ(第二引数)です。そのため、すべてのコンポーネントは幅をgetWidth関数で得たMainComponentの幅から40を引いた値、高さは20のコンポーネントサイズとなります。

よかったらシェアしてね!
目次
閉じる