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

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

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

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

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

JUCE
tutorial_component_parents_children - JUCE Tutorial: Parent and child components This tutorial introduces the hierarchical nature of the Component class whereby one component can contain one or more nest...

前回の記事「親と子のコンポーネント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をコピーしました!
目次