仕上がりイメージ
Rotary Sliderだけ変更して、こんな感じの見た目にする。針ではなく数値表示。大きさや色はProjucerで設計時に変更できるように。
LookAndFeelをオーバーライド
コード的な変更は、独自のLookAndFeelクラスを作って描画を変更したい部分だけメソッドをオーバーライドする。この例ではLookAndFeel_V4をベースに、LookAndFeel_V2のコードをJUCE本体からコピペして改変してる。
MyLookAndFeel.h
# pragma once
# include "../JuceLibraryCode/JuceHeader.h"
class IfwLookAndFeel : public LookAndFeel_V4
{
public:
IfwLookAndFeel() {}
~IfwLookAndFeel() {}
void drawRotarySlider (Graphics& g, int x, int y, int width, int height,
float sliderPosProportional, float rotaryStartAngle, float rotaryEndAngle,
Slider&) override;
};
MyLookAndFeel.cpp
# include "IfwLookAndFeel.h"
void IfwLookAndFeel::drawRotarySlider (Graphics& g, int x, int y, int width, int height,
float sliderPos, float rotaryStartAngle, float rotaryEndAngle,
Slider& slider)
{
const float radius = jmin (width / 2, height / 2) - 2.0f;
const float centreX = x + width * 0.5f;
const float centreY = y + height * 0.5f;
const float rx = centreX - radius;
const float ry = centreY - radius;
const float rw = radius * 2.0f;
const float angle = rotaryStartAngle + sliderPos * (rotaryEndAngle - rotaryStartAngle);
const bool isMouseOver = slider.isMouseOverOrDragging() && slider.isEnabled();
if (radius > 0.1f) // was 12.0f)
{
if (slider.isEnabled())
//g.setColour (slider.findColour (Slider::rotarySliderFillColourId).withAlpha (isMouseOver ? 1.0f : 0.7f));
g.setColour (slider.findColour (Slider::thumbColourId).withAlpha (isMouseOver ? 1.0f : 0.7f));
else
g.setColour (Colour (0x80808080));
const float thickness = isMouseOver? 0.8f : 0.85f; // was 0.7f;
{
Path filledArc;
filledArc.addPieSegment (rx, ry, rw, rw, rotaryStartAngle, angle, thickness);
g.fillPath (filledArc);
}
{
/* Draw value text instead of needle
const float innerRadius = radius * 0.2f;
Path p;
p.addTriangle (-innerRadius, 0.0f,
0.0f, -radius * thickness * 1.1f,
innerRadius, 0.0f);
p.addEllipse (-innerRadius, -innerRadius, innerRadius * 2.0f, innerRadius * 2.0f);
g.fillPath (p, AffineTransform::rotation (angle).translated (centreX, centreY));
*/
//g.setColour(Colours::white);
String valueText = slider.getTextFromValue(slider.getValue());
int textWidth = (int)(((float)width) * 0.55f);
int textHeight = (int)(((float)height) * 0.25f);
int textX = (width - textWidth) / 2;
int textY = (height - textHeight) / 2;
//g.setColour (slider.findColour (Slider::textBoxBackgroundColourId));
g.setColour (Colour(0x40000000));
g.fillEllipse(x, y, width, height);
g.setFont (Font (slider.getTextBoxHeight(), Font::plain).withTypefaceStyle ("Regular"));
g.setColour (slider.findColour (Slider::textBoxTextColourId).withAlpha (isMouseOver ? 1.0f : 0.7f));
g.drawText(valueText, textX, textY, textWidth, textHeight, Justification::centred);
}
if (slider.isEnabled())
g.setColour (slider.findColour (Slider::rotarySliderOutlineColourId));
else
g.setColour (Colour (0x80808080));
Path outlineArc;
outlineArc.addPieSegment (rx, ry, rw, rw, rotaryStartAngle, rotaryEndAngle, thickness);
outlineArc.closeSubPath();
g.strokePath (outlineArc, PathStrokeType (slider.isEnabled() ? (isMouseOver ? 2.0f : 1.2f) : 0.3f));
//auto lineW = jmin (8.0f, radius * 0.5f);
//g.strokePath (outlineArc, PathStrokeType (lineW, PathStrokeType::curved, PathStrokeType::rounded));
}
else
{
if (slider.isEnabled())
//g.setColour (slider.findColour (Slider::rotarySliderFillColourId).withAlpha (isMouseOver ? 1.0f : 0.7f));
g.setColour (slider.findColour (Slider::thumbColourId).withAlpha (isMouseOver ? 1.0f : 0.7f));
else
g.setColour (Colour (0x80808080));
Path p;
p.addEllipse (-0.4f * rw, -0.4f * rw, rw * 0.8f, rw * 0.8f);
PathStrokeType (rw * 0.1f).createStrokedPath (p, p);
p.addLineSegment (Line<float> (0.0f, 0.0f, 0.0f, -radius), rw * 0.2f);
g.fillPath (p, AffineTransform::rotation (angle).translated (centreX, centreY));
}
}
カスタマイズしたProjucerを作成
同じ変更をProjucer > Utility > UI > Jucer_ProjucerLookAndFeel.h/cppにも追加してProjucerをビルドすると、Projucer上でも見た目を変えられる。カスタマイズしたLookAndFeelで色はthumbを、フォントサイズはtext box heightを使うようにしてあるので、Projucer上で変更できて便利。フォントサイズをSliderの大きさに合わせて自動変更にしていないのは意図的なもの(用途によってそうしたければすればよい)。