Creating custom GUIs


#1

Hello,

I’m trying to learn how to create custom GUIs, so for example, I would like to know how to make a slider widget in juce have a different knob than the one provided.
My questions are:

If I have an image of the knob I want in png (or other) format how can I implement that into a slider widget?
Perhaps the best way would be to draw the knob completely in code?

I was thinking that I would have to make a sublcass from the Slider class but I’m a bit lost as to what needs to be reimplemented.
Can someone help me get on the right track? Any tips or guidance I would really appreciate it!
Thank you.


#2

Search for the forum index for “image slider” “imageslider” “filmstrip” and so on. This has been covered a few times, and there are some code solutions in the forum that work. Someone else might chime in with the current state of the art. The above searches presume that you are using a filmstrip image for your knobs, a la VST GUI (i.e. the sort of thing that Knobman outputs).

I use the geometric primitives in Juce & my own LookAndFeel classes to create the Valhalla DSP plugin controls. This works with my own preferences for minimalist 2D GUIs, but I know that some people HATE my GUIs. Theoretically, you could use pure vector graphics to create your controls, but once you get beyond a certain level of complexity you may wish to rotate an image, or use a filmstrip image.

Sean Costello


#3

I am also subclassing the LookAndFeel.
The images for the slider I add with the Introjucer and load them from the “BinaryData.h”

So I do something along the following lines, for drawing a custom knob on a vertical slider:

class PluginLookAndFeel : public LookAndFeel
{
public:
    PluginLookAndFeel()
{
    verticalSliderKnob = ImageCache::getFromMemory (BinaryData::Vertical_Slider_Knob_png, 
                                                     BinaryData::Vertical_Slider_Knob_pngSize);
}
    void drawLinearSliderThumb(Graphics& g,
                               int x, int y,
                               int width, int height,
                               float sliderPos,
                               float minSliderPos,
                               float maxSliderPos,
                               const Slider::SliderStyle style,
                               Slider& slider)
{
    if (style != Slider::LinearVertical)
        LookAndFeel::drawLinearSliderThumb(g, x, y, width, height, sliderPos, minSliderPos, maxSliderPos, style, slider);
    else
    {
        g.setOpacity(1.0);
        int centerX = x + width /2;
        int centerY = sliderPos;
        float widht = verticalSliderKnob.getWidth();
        g.drawImageAt(verticalSliderKnob,centerX - verticalSliderKnob.getWidth()/2, 
                                          centerY - verticalSliderKnob.getHeight()/2);      
    }
}
private:
    Image verticalSliderKnob;
};

Not sure if this is the best way, but it works for me.


#4

Thanks for the post! I’m actually subclassing from the Slider class which I know is not the best way but it’s working for now…, so I’m a bit confused how to do it subclassing from the LookAndFeel class, so once you have something like the code you posted, you create a slider and then set the LookAndFeel with setLookAndFeel()?
I’ve tried several things with my own LookAndFeel implementation like you have but I can’t seem to get it to work…


#5

Hello xtraction,

You can do this with a static method of the LookAndFeel Object:

LookAndFeel::setDefaultLookAndFeel(&myOwnLookAndFeel);

This makes your new look and feel the default one. This look and feel then applies to the whole application/plugin.


#6

it seems using look and feel you can replace the default set of graphical features for your own, how would you accomplish using several different looking knobs and sliders in the same project? would you create several lookandfeel classes and constantly switch between them before theyre drawn or can 1 lookandfeel support several different images/graphical calls?


#7

Each component can have its own LookAndFeel set see Component::setLookAndFeel. So each look and feel represents one set of styled widgets. If you need different styled sliders just create 2 different LookAndFeels, make sure you have at least 1 instance of each (they can be shared between components) and then apply them with the above method.

Its worth noting that look and feels do propagate down the component hierarchy so if a component hasn’t had a look and feel explicity set it will use its parents and so on until it uses the default look and feel set by LookAndFeel::setDefaultLookAndFeel;