スライダーオブジェクトも何気なく使用していました。改めて復習もかねてアプリの実装です。
基本は押さえておきたいね~
JUCEプログラミングチュートリアルの「Interface Design」、「The Slider class」を勉強していきます。今まで利用してきたスライダークラスですが、ここで、チュートリアルの項目として実装するアプリを作成して、より理解を深めていきたいと思います。
公式のチュートリアルページはこちらになります。
https://docs.juce.com/master/tutorial_slider_values.html
こんな人の役に立つかも
・JUCEプログラミングを勉強している人
・JUCEチュートリアル「The Slider class」をやっている人
・JUCEのスライダークラスについて知りたい人
デモアプリの概要
チュートリアルでは、次のような画面のアプリを作成していきます。Frequencyというスライダーコンポーネントと、DurationというスライダーコンポーネントがGUIに配置されたアプリです。
片方の値を設定すると、もう片方の値も連動して動く仕組みになっています。Frequency = 1/Durationという関係性が成り立つように連動するような仕組みのアプリとなります。
例えば、600Hzに設定すると、1/600=0.0016667sとなるような関係性です。
デモアプリの実装
プロジェクトの準備
Projucerの「GUI」テンプレートを利用してアプリを実装していきます。
MainComponent.h
MainComponent.hに次のようにいくつか追加しました。
class MainComponent : public juce::Component
,public juce::Slider::Listener//[1]追加しました。
{
public:
//...略...
//[2]リスナー関数を追加します。
void MainComponent::sliderValueChanged(juce::Slider* slider) override;
private:
//[3]コンポーネントを追加します。
juce::Slider frequencySlider;
juce::Label frequencyLabel;
juce::Slider durationSlider;
juce::Label durationLabel;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)
};
[1]で、スライダーの値変化を取得するため、「Slider::Listener」クラスを継承します。[2]で、sliderValueChanged関数をオーバーライドして、スライダーの値が変化したときの処理関数を定義しました。他にも、スライダーのドラッグ開始時などに反応する関数などがあるようです。Juce::Listenerクラスのドキュメントで確認できます。
[3]では、今回のアプリに利用するスライダー2つと、ラベル2つをprivateなメンバとして定義しておきます。
MainComponent.cpp
次に、MainCopmonent.cppに処理を追加していきます。
コンストラクタ
コンストラクタはアプリ起動時に実行され、コンポーネントの初期化処理などを記載していきます。
MainComponent::MainComponent()
{
//[1]frequencySliderの設定です。
addAndMakeVisible(frequencySlider);
frequencySlider.setRange(50, 5000.0);
frequencySlider.setTextValueSuffix(" Hz");
frequencySlider.addListener(this);
//[2]frequencySliderの左に表示する「Frequency」の文字ラベルの設定です。
addAndMakeVisible(frequencyLabel);
frequencyLabel.setText("Frequency", juce::dontSendNotification);
frequencyLabel.attachToComponent(&frequencySlider, true);
//[3]durationSliderの設定です。
addAndMakeVisible(durationSlider);
durationSlider.setRange(1.0 / frequencySlider.getMaximum(),
1.0 / frequencySlider.getMinimum());
durationSlider.setTextValueSuffix(" s");
durationSlider.addListener(this);
//[4]durationSliderの左に表示する「Duration」の文字ラベルの設定です。
addAndMakeVisible(durationLabel);
durationLabel.setText("Duration", juce::dontSendNotification);
durationLabel.attachToComponent(&durationSlider, true);
//[5]frequencySliderの値を500に設定します。
frequencySlider.setValue(500.0);
//[6]ウィンドウサイズを設定します。
setSize (600, 90);
}
すべてのコンポーネントで、addAndMakeVisible関数を使いコンポーネントを可視化します。
[1]では、frequencySliderの初期設定を行います。setRange関数は、スライダーの上限、下限値を設定します。50~5000に設定しました。次に、setTextValueSuffix関数で、数値の後ろにつく単位を設定します。「Hz」という単で表示されるようにしています。そして、addListener関数で、リスナー関数へhもづけを行います。これで、Slider::ListenerクラスからオーバーライドしたsliderValueChanged関数の処理が反応するようになります。
[2]では、frequencySliderの左に表示される「Frequency」の文字を表示するためのラベルコンポーネントを初期化します。setTxet関数で「Frequency」と、表示する文字列を設定します。第二引数のNotification Typeでは、外部からの文字の変更を受け付けない設定にしています。最後に、attachToComponent関数でfrequencySliderの左側にくっつくようになります。
[3]と[4]も同様のスライダーとラベルコンポーネントの設定です。[3]では、最大値と最小値をFrequencyとの関係性から計算式に変更しています。最小値は1/50、最大値は1/5000とすることで最小値と最大値の変更を最初のスライダーの値変更のみで変化するようにしています。
[5]では、FrequencySliderの初期値を500にしています。そして、[6]でウィンドウサイズを設定してコンストラクタでの初期化は完了です。
paint関数
paint関数にデフォルトで入っている処理は削除しておきます。
void MainComponent::paint (juce::Graphics& g){}
resized関数
描画領域にスライダーを配置します。setBoundsでひとつづつ配置する基本的な方法で配置しています。
GUIのレイアウト配置のテクニックについては、以前のチュートリアル記事に記載しましたので、発展的なテクニックは以前の記事をご参照ください。
void MainComponent::resized()
{
auto sliderLeft = 120;
frequencySlider.setBounds(sliderLeft, 20, getWidth() - sliderLeft - 10, 20);
durationSlider.setBounds(sliderLeft, 50, getWidth() - sliderLeft - 10, 20);
}
frequencySliderは左上原点から(120,20)の位置に、描画領域の幅から130を引いた幅、高さ20の大きさで配置します。ラベルは自動的に左にくっつくように指定しましたので、左の幅120の余白部分にラベル「Frequency」が表示されることになります。durationSliderは原点のYの値を50として、少し下に配置しています。
sliderValueChanged関数
スライダーの値が変化したときに呼び出される処理です。
void MainComponent::sliderValueChanged(juce::Slider* slider)
{
//[1]frequencySliderの値が変化したときです。
if (slider == &frequencySlider)
durationSlider.setValue(1.0 / frequencySlider.getValue(), juce::dontSendNotification);
//[2]durationSliderの値が変化したときです。
else if (slider == &durationSlider)
frequencySlider.setValue(1.0 / durationSlider.getValue(), juce::dontSendNotification);
}
最後に、cppの一番下にslideValueChanged関数を定義して完了です。
[1]と[2]のように、どのスライダーコンポーネントが反応したかを条件で分岐させます。そして、それぞれの場合にsetValue関数で連動しているスライダーの値を書き換えます。値は、それぞれの関係式から、1/〇〇とするだけなので、この計算式をsetValueの第一引数として渡します。