How To Make Click&Drag Number Box Slider (Without the Slider)?


I don’t know how this type of UI element is called but I need a simple Number or BumberBox on wich i can change the value with draging (horizontal or vertical).
what is the best way of doing this?


You can get that behaviour with a slider if you tweak its options - have a look at some of the variations of slider shown in the demo app on the ‘widgets’ page


Create a Component with a hidden Slider.



well… how can i do this?


thanks but there is not one single example on how to change the values by draging on the number box…
what would be the workaround for this?


I’d have thought the LinearBarHorizontal style would do pretty much what you need? If you really don’t want it to show the bar you could make it transparent or give it a custom look+feel to make it look exactly how you want.


is the LookAndFeel_V2::getSliderLayout() the right thing to override?


You can see all the relevant lookandfeel methods in the Slider::LookAndFeelMethods class. Which ones you implement will obviously depend on what you want to do.


ah yes! LinearBarHorizontal with Alpha = 0 does it!!
but how can I get rid of the outline? where is it located?

many thanks!

Another slider suggestion -> pure label style

No idea offhand, you can probably find it in the lookandfeel methods somewhere. Or set its colour to transparent.


ok thank you very much! found it.
if someone is interested:

you have to override
drawLabel (Graphics& g, Label& label)
this is how mine looks:

void OtherLookAndFeel::drawLabel (Graphics& g, Label& label)
    g.fillAll (label.findColour (Label::backgroundColourId));
    if (! label.isBeingEdited())
        const float alpha = label.isEnabled() ? 1.0f : 0.5f;
        Font font (getLabelFont (label));
        font.setHeight (fontHeight);
        g.setColour (label.findColour (Label::textColourId).withMultipliedAlpha (alpha));
        g.setFont (font);
        Rectangle<int> textArea (label.getBorderSize().subtractedFrom (label.getLocalBounds()));
        g.drawFittedText (label.getText(), textArea, label.getJustificationType(),
                          jmax (1, (int) (textArea.getHeight() / font.getHeight())),
        g.setColour (Colours::transparentBlack);
    else if (label.isEnabled())
        g.setColour (Colours::transparentBlack);
    g.drawRect (label.getLocalBounds());

and in the custom l+f:

setColour (Slider::thumbColourId, Colours::transparentBlack); //
setColour (Slider::trackColourId, Colours::transparentBlack); //
setColour (Slider::backgroundColourId, Colours::transparentBlack); //


I’ll give you the header of my class… which should give you some ideas… my class has some additional functionality you won’t require…

class CNumericLabelLF : public LookAndFeel_V3
    CNumericLabelLF() {};

    void drawLinearSliderBackground (Graphics& , int , int , int , int , float , float , float , const Slider::SliderStyle , Slider& ) override

    void drawLinearSliderThumb (Graphics& , int , int , int , int , float , float , float , const Slider::SliderStyle , Slider& ) override

    Font getLabelFont (Label& label) override
        return label.getFont().withHeight (11.0);




class CNumericSlider;

class CNumericLabel : public Label,
                      public Slider::Listener

    CNumericLabel (const String& componentName = String(), const String& labelText = String());

    void resized() override;

    void sliderValueChanged (Slider* slider) override;
    void sliderDragEnded (Slider* slider) override;

    void setRange (int iMin, int iMax);

    void setDoubleClickReturnValue (int iDefault);

    void setValue (int iNewValue);

    void setIsTopValue (bool bIsMaxLabel)       { m_bIsMaxValue = bIsMaxLabel;          }

    int  getValue() noexcept                    { return m_iValue;                      }

    void setOppositeValue (int iOppositeValue)  { m_iOppositeValue = iOppositeValue;    }


    class CNumericSlider : public Slider

        CNumericSlider (CNumericLabel* pOwner) : m_pOwner (pOwner)
            setTextBoxStyle (Slider::NoTextBox, false, 70, 20);
            setSliderSnapsToMousePosition (false);

        ~CNumericSlider() {}

        void mouseDown (const MouseEvent& event) override

            Slider::mouseDown (event);

        void mouseEnter (const MouseEvent& event) override
            m_pOwner->setColour (Label::outlineColourId, Colours::grey);

            Slider::mouseEnter (event);

        void mouseExit (const MouseEvent& event) override
            m_pOwner->setColour (Label::outlineColourId, Colour (0x1000282));

            Slider::mouseExit (event);


        CNumericLabel*  m_pOwner;



    /** Receives callbacks when a CNumericLabel object changes.
    class  Listener

        virtual ~Listener() {}

        /** Called when a CNumericLabel object is changed.
        virtual void labelChanged (CNumericLabel* label) = 0;

        virtual void labelDragEnded (CNumericLabel* ) {}

    /** Adds a listener to receive callbacks when the value changes.
    void addListener (Listener* const listener);

    /** Removes a listener that was previously added with addListener(). */
    void removeListener (Listener* const listener);

    /** Updates the CNumericLabel's listeners.
     Call this to explicitly tell any registerd listeners that the value has changed.
	void updateListeners();


    int     m_iValue;
    int     m_iMinValue;
    int     m_iMaxValue;
    int     m_iDefaultValue;

    bool    m_bIsMaxValue;
    int     m_iOppositeValue;

    ScopedPointer<CNumericSlider>   m_pHiddenSlider;

    CNumericLabelLF m_Look;

    ListenerList<Listener> m_Listeners;


typedef CNumericLabel::Listener CNumericLabelListener;




thank you very much for sharing this!!