Changing Juce::Slider properties interrupts use of the slider

I have a row of juce::sliders used as a step sequencer.
Each time the stepper steps forward, I change the color of the current slider.
Problem is, if I am adjusting the value of the slider the ability to adjust gets cut off by the change of property. I’ll be in the middle of setting a value but then the mouse drag stops having an affect the moment the color of the slider is changed.

Is there a way to work around for. this?

maybe like this:
instantiate the look and feel class for the slider, add a custom color variable as a property.
change the drawing in the LAF to use the custom color.
now if redraw is triggered in slider self, the color will be used.

Could you elaborate on that a bit I’m not sure where to start to do that.

I am currently using:

  velocityCells[audioProcessor.theVelocities.currentStep]->setColour(juce::Slider::textBoxOutlineColourId   , juce::Colours::grey);
class sliderLAFClass : public juce::LookAndFeel_V4
{
public:
    Colour myColorToSwitch;

    void drawRotarySlider (Graphics& g,
    int x, int y, int width, int height,
    float sliderPosProportional,
    float rotaryStartAngle,
    float rotaryEndAngle,
    Slider&) override
    {

       // Use here ColorToSwitch

    }
}

   

class mySliderComponent    : public Slider
{
public:
    // … 
   mySliderComponent(){
     setLookAndFeel (sliderLAF);
  }
~mySliderComponent(){
        setLookAndFeel (nullptr);
    };

    sliderLAFClass sliderLAF;
}
-Set mySliderComponent. sliderLAF.myColorToSwitch to Colour( x, y, z)
-Call mySliderComponent.repaint if needed ( slidervaluechange will trigger repaint() itself)
1 Like

shows the problem, in case I wasn’t clear.

Why will this prevent the problem I was seeing?

LookAndFeel is the solution because it provides the draw methods for each slidertype. So it rules the way the slider draws itself.
I presumed the rotaryslider method, you have to lookup the method for your slidertype here:
https://docs.juce.com/master/classLookAndFeel__V4.html

Why would that prevent slider color changes from interrupting slider value drags by the user?

When my sequencer is running fast the color of the slider might change a couple times per second.

you’re interrupting the slider in its doings, using the LAF class will not interrupt the slider, it will change the way the slider represents itself.
I dont know exactly how you are interrupting the slider, but using lookandfeel is the standard method for circumventing such stuff afaik.

So I would give each slider it’s own lookandfeel?

Those are sliders in my video btw,
Used this technique:

you just need 1 laf class, but like shown in my example aboive, each slider has an instance of it onboard.

1 Like

I think you can best use drawButtonBackground() in the LAF.
just look up the code for LookAndFeel_V4::drawButtonBackground
copy that funcntion in class sliderLAFClass
add the custom colour usage there

I think what @loveslap would like to know why changing the colour actually tiggers the behaviour.
If you check the inner workings of juce_Slider you’ll see the following.
When the colour property is set the Slider::colourChanged method is called and it its turn it calls lookAndFeelChanged(). In lookAndFeelChanged() quite a few controls are being rebuild and this probably causes the mouse to cancel its dragging behaviour.

I personally think its quite odd that the Slider is being rebuild when just a colour is being changed. But atm that is just how it is.

So what @PaulDriessen is suggestion is to not use Slider::setColour, because that will cause a rebuild but use a custom property (you can add custom properties to any component using component.getProperties().set(“MyColor”, value)) and pick up this custom property in a custom lookAndFeel.
You only have to have one lookAndFeel instance for all your sliders, then override the draw method and pick up the custom property in the draw method.
Don’t forget to to call repaint on your slider after setting the custom property though because otherwise the colour change will not be picked up.

What you gain by this is that you have more control on what happens when you change the color of the slider. But this should never have been needed in the first place because a colour change should not cause a rebuild in my opinion.

Maybe the JUCE team can shed some light here, and maybe even fix the behaviour.

1 Like

I only want to change the color of one slider at a time, not change the color of all of them at once.

Yes, and if you use Properties as suggested above by @rebbur, you would be able to do that.

You set the Property depending whether you want the slider drawn differently or not.

Then in the draw method drawButtonBackground(), which will be called for all buttons, you examine the button’s Properties and pick up whether to change its color or not.

Properties are really useful for getting a single component of a certain class to do something different from all of its siblings without subclassing it or making a separate LookAndFeel.

Thanks for reporting @loveslap. I think this should be resolved on the latest commit on develop now. Let me know if you have any more problems.

I loaded the develop branch and now this block of code no longer works

void NewProjectAudioProcessorEditor::timerCallback()
 {
    // DBG("time for timer");
    if (audioProcessor.theVelocities.getCurrentPosition() != lastVelocityStep)
    {
//        DBG("velocityStep: " << audioProcessor.theVelocities.getCurrentPosition());
        
        velocityCells[lastVelocityStep]->setColour(juce::Slider::textBoxOutlineColourId  , juce::Colours::black);
        lastVelocityStep = audioProcessor.theVelocities.getCurrentPosition();
        
        velocityCells[audioProcessor.theVelocities.getCurrentPosition()]->setColour(juce::Slider::textBoxOutlineColourId   , juce::Colours::grey);
                                                    
    }

The cells no longer change colors.

But the slider value update is no longer interrupted.