LoginSignup
3
4

More than 5 years have passed since last update.

JUCEのSlider(の見た目)をカスタマイズする

Posted at

仕上がりイメージ

Rotary Sliderだけ変更して、こんな感じの見た目にする。針ではなく数値表示。大きさや色はProjucerで設計時に変更できるように。
Simulator Screen Shot - iPhone 5s - 2019-01-06 at 10.47.56.png

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の大きさに合わせて自動変更にしていないのは意図的なもの(用途によってそうしたければすればよい)。
スクリーンショット 2019-01-06 10.58.28.png

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4