スライダーコンポーネントのカスタマイズなどを勉強しました。
今まで何気なく使ってきた点のまとめみたいな内容だね〜
JUCEプログラミングチュートリアルの「Interface Design」、「The Slider class」の続きを勉強していきます。今回は、スライダーコンポーネントのカスタマイズ部分などについてです。
公式のチュートリアルページはこちらになります。
こんな人の役に立つかも
・JUCEプログラミングを勉強している人
・JUCEチュートリアル「The Slider class」をやっている人
・JUCEのスライダークラスについて知りたい人
スライダーのカスタマイズ
テキストボックスのサイズ
MainComponent.cppのコンストラクタに次のプログラムを追記しました。
MainComponent::MainComponent()
{
//...略...
frequencySlider.setTextBoxStyle(juce::Slider::TextBoxLeft, false, 160, frequencySlider.getTextBoxHeight());
durationSlider.setTextBoxStyle(juce::Slider::TextBoxLeft, false, 160, durationSlider.getTextBoxHeight());
//...略...
sliderクラスのsetTextBoxStyle関数を使うと、スライダーに含まれているテキストボックスのカスタマイズができます。この関数の第一引数には、TextEntryBoxPositionに定義された値を渡すことで、テキストボックスがスライダーに隣接する方向が指定できます。「TextBoxLeft」とすることで、スライダーの左側にテキストを表示するようにしました。第二引数はfalseにしてテキストボックスの値の書き換えを有効にしています。そして、第三引数でテキストボックスの幅、第四引数でテキストボックスの高さを指定しています。今回、幅を160pixel、高さはスライダーコンポーネントの高さを取得しています。

非線形なスライダー値の変化
周波数を扱うときは、スライダーの値が線形というよりは、対数的な変化をする方がより直感的に操作することができます。周波数が高くなると、少しのスライダーの動作で大きく周波数が移動したほうが直感的です。
setSkewFactorFromMidPoint関数を使うと、スライダーの中心となる値を設定することができます。
たぶん、線形から、右のように、中心と設定したところを50%としたいい感じの曲線で増減します。

対数的な変化、ということはわかりましたが、対数で変化というところが、具体的にどのように変化しているかは知ることができていません。
非線形という言葉でふわっとさせた・・・
スライダーをこのように変化させるので、次のようにコンストラクタにプログラムを追加しました。
frequencySlider.setTextBoxStyle(juce::Slider::TextBoxLeft, false, 160, frequencySlider.getTextBoxHeight());
durationSlider.setTextBoxStyle(juce::Slider::TextBoxLeft, false, 160, durationSlider.getTextBoxHeight());
//この2行を追加しました。
frequencySlider.setSkewFactorFromMidPoint(500);
durationSlider.setSkewFactorFromMidPoint(0.002);
setSize(600, 90);
}
シンプルにリスナーを定義する
ボタンのリスナー関数でもやりましたが、スライダーコンポーネントでも、「on〇〇」関数にラムダ式で処理内容を定義して、シンプルにリスナを定義することができます。
今回は、スライダー値が変化したときの処理なので、「onValueChanged」関数を利用して今までと同じように動作するアプリに変更してみます。
まずは、Listenerクラスの継承を削除しました。
class MainComponent : public juce::Component
//,
//public juce::Slider::Listener
{
//...略...
次に、sliderValueChanged関数のオーバーライドを削除します。
public:
//...略...
//void sliderValueChanged(juce::Slider* slider) override;
そのため、cppファイルに定義したsliderValueChanged関数も削除しておきます。
/*
void MainComponent::sliderValueChanged(juce::Slider* slider)
{
if (slider == &frequencySlider)
durationSlider.setValue(1.0 / frequencySlider.getValue(), juce::dontSendNotification);
else if (slider == &durationSlider)
frequencySlider.setValue(1.0 / durationSlider.getValue(), juce::dontSendNotification);
}
*/
コンストラクタで、スライダーコンポーネントにaddListener関数で紐づけていた行を削除して、onValueChanged関数に直接処理内容を記載するように変更しました。
MainComponent::MainComponent()
{
//...略...
//frequencySlider.addListener(this);//削除します。
//↓変更後です。
frequencySlider.onValueChange = [this] { durationSlider.setValue(1.0 / frequencySlider.getValue(), juce::dontSendNotification); };
//durationSlider.addListener(this);
durationSlider.onValueChange = [this] { frequencySlider.setValue(1.0 / durationSlider.getValue(), juce::dontSendNotification); };
ラムダ式の内容は、別途関数として定義しても良いのですが、今回はとてもシンプルなプログラムなので、直接onValueChangeに記載しています。