JUCEプログラミング、Parent and child components、親と子のコンポーネント2

コンポーネントを親子に分けるといろいろと便利そうです。

GUIの描画という点でも実用的だね~

引き続き、JUCEチュートリアルの「Parent and child components」の項目をやっていきたいと思います。

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

前回の記事「親と子のコンポーネント1」もご参照ください。

こんな人の役に立つかも

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

・JUCEプログラミングのチュートリアルを進めている人

・Parent and child componentsチュートリアルを進めている人

目次

コンポーネントの親子関係

HouseComponent、RoofComponent、WallComponent、FloorComponentクラスを追加していきます。

クラスの親子関係は次のようになっています。HouseComponentの子としてRoof、Wallを作ります。

プログラミング

前回の記事で、「MainComponent」クラスと「SceneComponent」クラスにプログラムを分割しました。このプログラムをベースとして追加していきたいと思います。今回追加するのは、「SceneComponent.h」と「SceneComponentc.cpp」になります。全体として、MainComponentと、そのほかのクラス、というような分け方をすることになりました。

SceneComponent.h

WallとRoofは、Houseで使用するので、Houseより↑に記載、HouseとFloorはSceneで使用するので、Sceneより↑に記載するという点を注意してクラスの定義を行いました。

//WallComponentクラス
class WallComponent : public juce::Component
{
public:
    WallComponent();

    void paint(juce::Graphics& g) override;

    void resized() override;

private:

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(WallComponent)
};

//RoofComponentクラス
class RoofComponent : public juce::Component
{
public:
    RoofComponent();

    void paint(juce::Graphics& g) override;

    void resized() override;

private:

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(RoofComponent)
};

//FloorComponentクラス
class FloorComponent : public juce::Component
{
public:
    FloorComponent();

    void paint(juce::Graphics& g) override;

    void resized() override;

private:

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FloorComponent)
};

//HouseComponentクラス
class HouseComponent : public juce::Component
{
public:
    HouseComponent();

    void paint(juce::Graphics& g) override;

    void resized() override;

private:
    //[1]WallとRoofのコンポーネントを定義します。
    WallComponent wall;
    RoofComponent roof;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(HouseComponent)
};

class SceneComponent : public juce::Component
{
public:
    SceneComponent();

    void paint(juce::Graphics& g) override;

    void resized() override;

private:
    //[2]FloorとHouseのコンポーネントを定義します。
    FloorComponent floor;
    HouseComponent house;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SceneComponent)
};

全部のクラスに共通する基本的な事項としては、

①コンストラクタ

②paint関数

③resize関数

を作成する、という点でした。

[1]と[2]にて、それぞれ子となるコンポーネントを定義しています。

SceneComponent.cpp

#include "SceneComponent.h"
//[1]SceneComponentクラス
SceneComponent::SceneComponent()
{
    //[1-1]floorとhouseを可視化します。
    addAndMakeVisible(floor);
    addAndMakeVisible(house);
}

void SceneComponent::paint(juce::Graphics& g)
{
    g.fillAll(juce::Colours::lightblue);
}

void SceneComponent::resized()
{
    //[1-2]floorとhouseを配置します。
    floor.setBounds(10, 297, 580, 5);
    house.setBounds(300, 70, 200, 220);
}

//[2]FloorComponentクラス、描画関数のみ定義しておきます。
FloorComponent::FloorComponent(){}

void FloorComponent::paint(juce::Graphics& g)
{
    g.setColour(juce::Colours::green);
    g.drawLine(0.0f, (float)getHeight() / 2.0f, (float)getWidth(), (float)getHeight() / 2.0f, 5.0f);
}

void FloorComponent::resized(){}

//[3]HouseComponentクラス
HouseComponent::HouseComponent(){}

void HouseComponent::paint(juce::Graphics& g)
{
    //wallとroofを可視化します。
    addAndMakeVisible(wall);
    addAndMakeVisible(roof);
}

void HouseComponent::resized()
{
    //[3-1]roofとwallのマージンの幅を設定しています。
    auto separation = juce::jlimit(2, 10, getHeight() / 20);

    roof.setBounds(0, 0, getWidth(), (int)(getHeight() * 0.2) - separation / 2);
    wall.setBounds(0, (int)(getHeight() * 0.20) + separation / 2, getWidth(), (int)(getHeight() * 0.80) - separation);
}

//[4]WallComponentクラス、paintのみ実装します。
WallComponent::WallComponent(){}

void WallComponent::paint(juce::Graphics& g)
{
    g.fillCheckerBoard(getLocalBounds().toFloat(), 30, 10,
    juce::Colours::sandybrown, juce::Colours::saddlebrown);
}

void WallComponent::resized(){}

//[5]RoofComponentクラス、paintのみ実装します。
RoofComponent::RoofComponent(){}

void RoofComponent::paint(juce::Graphics& g)
{
    g.setColour(juce::Colours::red);

    juce::Path roof;
    roof.addTriangle(0.0f, (float)getHeight(), (float)getWidth(), (float)getHeight(), (float)getWidth() / 2.0f, 0.0f);
    g.fillPath(roof);
}

void RoofComponent::resized(){}

[1]floorとhouseをコンストラクタで可視化して、resize関数で配置します。

[2]は、Floorを描画します。緑色の線です。getHeightとgetWidth関数でComponentの大きさを取得して、それをもとに配置しています。

[3]のHouseComponentクラスでは、roofとwallを子コンポーネントとして持つのでこれらを可視化して、配置しています。

resize関数でのroofとwallの配置では、まず「separation」という変数に、roofとwallをぴったりとくっつけないようにする空間の値を取得しています。jlimit関数は、(下限、上限、値)という引数で、値に上限と下限を設定して返しています。「値」の計算式の結果は最小値2と最大値10というようになります。

[4]のwallコンポーネントは、paint関数内でレンガ上の矩形を描画します。

[5]のroofコンポーネントは、paint関数内で三角形を描画しています。

子コンポーネントの仕組みがよくわかってきました。

次の記事、「親と子のコンポーネント3」はこちらです。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次