Repainting only a portion of a component

I have some meter components that display midi data in a sort of audio-meter-type look. Running 6-8 channels of them at the same time is somewhat of a CPU hit.

In order to optimize these, I was playing with the idea that if, while they are running, only the right edge of the fill (of a left-to-right horizontal meter) is actually changing most of the time, that I could store the last drawn rectangle, compare to the new portion to be drawn, and only draw a small rectangle of the part that has changed, thereby avoiding redrawing the whole meter bar (which is a left-to-right gradient).

The problem I can’t seem to get by is that, if I only redraw a portion of the fill, the rest of it gets erased no matter what I do.

I’ve tried it with setOpaque() true/false, I’ve tried using reduceClipRegion() to set only the portion to repaint, but the rest of the meter gets erased and fills with the default juce color.

What I wanted to achieve was to draw the fill gradient from the left to the right when the meter starts running, then just update a small rectangle on the right side as it’s changing, and not erase the portion of the fill that was already drawn and just leave it there. Is this possible?

Perhaps you can use the form of repaint() that takes parameters.

void juce::Component::repaint(int x, int y, int width, int height)

I use this to draw midi notes going to the right as they are played without erasing the existing notes to the left.

1 Like

Thanks, that was a good suggestion, except:

If I calculate the part that needs to be redrawn and then call repaint(new area), by the time the actual paint() happens, the area needing to be redrawn may have changed. Since repaint() calls an asynchronous draw operation.

I wish I could figure out what repaint(Rectangle area) does versus a standard repaint(). I would assume it just sets the clipRegion, but if that were true I could use reduceClipRegion() myself in my paint() override and achieve the same result, but I can’t get that to work…

Actually, I was able to get that suggestion to work, so thanks for that!

1 Like

That’s awesome! The parameterized version of repaint() is certainly less well known, but can be a life saver in certain situations.

Glad it helped!

@bwall thanks for sharing that repainting method. I didn’t know that.

I’ve turned to putting my background in one component and my real-time info in another component with no fill all or clear fill all. Nested within a parent to cut down times and segment the drawing.

This has also caused similar painting issues though, when not properly updated.