JUCEプログラミング、Listeners and Broadcasters、リスナー関数の定義の仕方

コンポーネントのイベントハンドラのようなものですね〜

定義の仕方も2通りあるみたいだね

JUCEプログラミング、「Interface Design」の「Listeners and Broadcasters」チュートリアルをやっていきます。リスナーやブロードキャスターについては、過去のチュートリアルでも何気なく利用してきましたが、ここで、再度ちゃんと勉強したいとおもいます。

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

目次

こんな人の役に立つかも

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

・JUCEチュートリアル「Listeners and Broadcasters」をやっている人

・JUCEコンポーネントのリスナーについて勉強している人

基本となるアプリの準備

チュートリアルでは、基本となるアプリに変更を加えていくことで進みますので、まずは最初の基本となるアプリを準備します。

Projucerの「GUI」テンプレートをもとに作成していきます。

MainComponent.h

MainComponent.hには、次のように、テキストボタンと、ラベルを準備しておきます。

class MainComponent  : public juce::Component
{
//...略...
private:
    //次のコンポーネントを準備しておきます。
    juce::TextButton checkTheTimeButton;
    juce::Label timeLabel;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)
};

MainComponent.cpp

「GUI」テンプレートの次の部分を変更していきます。

コンストラクタ

ボタンとテキストの初期化を行います。

MainComponent::MainComponent()
{
    addAndMakeVisible(checkTheTimeButton);
    checkTheTimeButton.setButtonText("Check the time...");

    addAndMakeVisible(timeLabel);
    timeLabel.setColour(juce::Label::backgroundColourId, juce::Colours::black);
    timeLabel.setColour(juce::Label::textColourId, juce::Colours::white);
    timeLabel.setJustificationType(juce::Justification::centred);

    setSize(600, 110);
}

resized関数

ボタンとテキストの配置を行うように変更します。

void MainComponent::resized()
{
    checkTheTimeButton.setBounds(10, 10, getWidth() - 20, 40);
    timeLabel.setBounds(10, 60, getWidth() - 20, 40);
}

paint関数

paint関数は、何もしないように変更します。

void MainComponent::paint (juce::Graphics& g)
{}

これでチュートリアルの最初の状態ができました。

実行すると、次のようなGUIのアプリが出てきます。

リスナーの追加

各コンポーネントのリスナークラスを継承することで、コンポーネントの変化を取得することができるようになります。

Listenerクラスの継承

まずは、ボタンの変化を取得してみます。MainComponent.hのMainComponetnクラスに、「Button::Listener」クラスを継承させます。

class MainComponent  : public juce::Component
    , public juce::Button::Listener//継承を追加しました。
{
public:
//...略...

Listenerクラスは、それぞれのコンポーネントに存在しています。Sliderコンポーネントは「Slider::Listener」クラスのように、コンポーネントに合わせたListenerクラスを継承することで、いろいろなコンポーネントの変化を取得できます。

リスナー関数のオーバーライド

Button::Listenerクラスの関数、「buttonClicked」関数をオーバーライドして実装します。

MainComponent.hに次のようにオーバーライドします。

public:
//...略...
    void resized() override;

    void buttonClicked(juce::Button* button) override;

private:
//...略...

そして、cppに処理内容を実装していきます。MainComponent.cppファイルの一番下に次のようにbuttonClicked関数を追加しました。

void MainComponent::buttonClicked(juce::Button* button)
{
    if (button == &checkTheTimeButton)//[1]
    {
        auto currentTime = juce::Time::getCurrentTime();//[2]

        //[3]
        auto includeDate = true;
        auto includeTime = true;
        auto currentTimeString = currentTime.toString(includeDate, includeTime);

        timeLabel.setText(currentTimeString, juce::dontSendNotification);//[4]
    }
}

[1]のように、どのボタンの処理かを判定します。button引数にボタンのポインタが渡されるので、checkTheTimeButtonコンポーネントであることを確認します。[2]では、Timeクラスで現在時間を取得します。[3]では、Timeクラスの「toString」関数で文字列に変換しています。[4]で、Labelクラスの「setText」関数でラベルオブジェクトtimeLabelへ文字列をセットします。

リスナー関数の紐づけ

リスナー関数を初期化時に紐づけします。コンストラクタで次の処理を追加しました。

MainComponent::MainComponent()
{
    addAndMakeVisible(checkTheTimeButton);
    checkTheTimeButton.setButtonText("Check the time...");
    checkTheTimeButton.addListener(this);//←追加しました。
//...略...

また、デストラクタでリスナーを取り除く処理を追記しました。

MainComponent::~MainComponent()
{
    checkTheTimeButton.removeListener(this);//追加しました。
}

シンプルな方法でリスナーを実装する

Button::Listenerクラスを継承する方法でリスナー関数を実装しましたが、ラムダ式を利用した方法でシンプルにリスナー関数を実装できます。

MainComponent.h

class MainComponent  : public juce::Component
    //, public juce::Button::Listener//[1]継承を削除します。
{
public:

//...略...
    void resized() override;

    //[2]buttonClicked関数を削除します。
    //void buttonClicked(juce::Button* button) override;


private:
    juce::TextButton checkTheTimeButton;
    juce::Label timeLabel;

    //[3]checkTime関数を追加しました。
    void checkTime() {
        auto currentTime = juce::Time::getCurrentTime();

        auto includeDate = true;
        auto includeTime = true;
        auto currentTimeString = currentTime.toString(includeDate, includeTime);

        timeLabel.setText(currentTimeString, juce::dontSendNotification);
    };

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)
};

今まで作成してきたものを削除([1]と[2])、[3]のように、buttonClicked関数で行ってきた処理をcheckTime関数というものに定義しました。

MainComponent.cpp

デストラクタの内容を削除、buttonClicked関数を削除します。そして、コンストラクタに以下のようにonClicked関数でラムダ式を定義します。

MainComponent::MainComponent()
{
    addAndMakeVisible(checkTheTimeButton);
    checkTheTimeButton.setButtonText("Check the time...");
    //checkTheTimeButton.addListener(this);//←[1]削除します。
    checkTheTimeButton.onClick = [this] { checkTime(); };//[4]追加しました。


//...略...

//デストラクタ
MainComponent::~MainComponent()
{
    //checkTheTimeButton.removeListener(this);//←[2]削除します。
}

//↓[3]削除します。
/*void MainComponent::buttonClicked(juce::Button* button)
{
    if (button == &checkTheTimeButton)
    {
//...略...

[1]と[2]と[3]の、いままで使用していた処理を削除しました。[4]では、ButtonクラスのonClicked関数を使用して、ラムダ式に処理を記述することで、リスナーを定義することができます。

on〇〇関数を利用することで、シンプルにリスナーを定義できるようです。例えば、sliderクラスにも同様の関数が定義してあります。

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