Can I send variables to repaint()? ex. repaint(meter) repaint(treshold)


#1

I don’t want to repaint everything inside the window. So first I was thinking of making an extra function ex. AudioProcessorEditor::tresholdReached(Graphics& g){} and paint everything in there. But that didn’t work.

Then I read a post by Jules that you should use the paint function for everything that needs to be refreshed a lot. So I was thinking of using if() statements inside the AudioProcessorEditor::paint (Graphics& g) function. And just sending it variables. Is this accepted practice or not? Is it even possible?


#2

Component::paint is a virtual method declared and called by JUCE itself, so no, you can not add extra arguments to it. Whatever custom state your paint implementation needs to use, needs to come from member variables of your component subclass. The same goes for Component::repaint() but of course you could add a differently named method like updateView(SomeEnumOrFlagType whattoupdate) which would update an internal state variable what the paint method could then check.

Component::repaint() has overloads that can update a partial rectangular portion of the component but the component’s paint method then needs to figure out how to do that efficiently. (The dirty area is in the Graphics object.)


#3

This goes a bit over my head. But after reading this I would use a private bool and then check inside the paint method if it’s true or false, paint it and then set it to false. Or is there a better practice? Anyway thanks for the fast reply.


#4

Using dirty flag member variables is common practice and it’s pretty difficult to do anything else apart from just avoiding unnecessary repaint calls.

If you have a complicated component, you should of course consider making separate components for the different parts. (IMHO it’s not always the right thing to do, but should still be considered on a case by case basis.)


#5

You are never calling paint, the OS is calling it. That’s why you can’t send it any arguments with it.
But you can change the state of your component (I understand you are creating a meter?) that us then used in the paint() method. e.g. the threshold you want to visualise is usually a member variable. You can evaluate that in your paint call.
However, like it was mentioned before, you should always paint everything in your paint call. If there are regions, that don’t need painting, or that are occluded or cut off, the rendering backend (Graphics) will skip the irrelevant paint operations anyway.


#6

Oh thanks that’s interesting to know. So I don’t have to worry, and I can just throw everything in the paint() method? It is quite confusing because with the debug show paint flag (I forgot what it actually was) everything is flashing. Yes I’m making a meter but that’s not the focus of the application. I just wanted to paint multiple things at different times without repainting everything. Plus I was afraid that my paint class was going to look super messy in the future.

The treshold is not treshold for the meter, I haven’t implemented envelope follower and nice slow graphics. It’s a slider and when the volume goes over the treshold it has to send a midi note.


#7

If you call repaint(), the default will call repaint (getLocalBounds()), which will paint the whole component.
Does it still flash, if you give it specific bounds in repaint()?

I am not familiar with the debug show paint, so I can’t tell, if it recognises clipped bounds…


#8

Your editor shouldn’t be repainting your meters… your meters should be a self encapsulated class which receives data from your audio processor class’ thread and repaints itself (usually using a timer)… your meters’ repaints should try to repaint as little as possible in the meter component class.

Rail


#9

As Rail said, your meters should be in their own class that handles the repaints. Then, follow some general tips for paints/repaints;

  1. Paint only when necessary (30Hz is often sufficient), again this is controlled by a timer in the meter class
  2. Put in some logic to paint only when something changes, so for example…
    if(newMeterValue != oldMeterValue)
    {
        // paint meter element
    }
  1. Examine how you are drawing the meter elements to assure you are drawing in the most efficient manner. For example, it may be more efficient to draw a line with fillRect() instead of drawLine(). Study the code base and read the accompanying comments to learn more.