Hi,
I know that this question discussed thousand of times, but after the reading of the topics, I still confused with a simple example.
The situation is trivial.
I have an editor. The editor has one child and a timer. Inside the callback, I called the child method which triggers repaint().
And after this parent method Paint is called. But and I don’t want it to be called. I want to repaint only the child object.
I tried to use opaque(true) and still nothing.
So you call a child’s method which in turn calls the child’s repaint(), and this eventually causes the parent’s paint() to be called. First, you’d have to be sure this is the cause -as paint() is called asynchronously, something else might be causing it. If you’re sure this is the cause, I guess setOpaque(true) on the child should have avoided it. If it doesn’t (I’ve never been sure about that), I can suggest not having backgrounds painted in parent components. Have another child as the background, so that it’s a sibling of the components above it, and if it doesn’t repaint often, set it bufferedToImage.
Yes. I tried with opaque and still nothing.
Even more, I gave you a short example. In a real project, I have many siblings and all of them start repainting after I call repaint inside the first child’s method which is called from the callback… If I comment only this single line “repaint();” - everything is ok and nothing happens.
That’s the reason why I decided to simplify the project just to leave the editor and one child, just to understand why it’s happening.
Well, I never took the whole trip of understanding the painting system -it involves a lot of stuff between Component, ComponentPeer and especially its native implementations. There are some known caveats, like not setting paintingIsUnclipped to components with children. So I just don’t paint expensive backgrounds in parents -making them separate children is a safe bet.
Yes. It was my idea in the beginning, but what I see now, that every element is repainting and during debug see that paintComponentAndChildren is calling.
paintComponentAndChildren() is always called. Painting starts in ComponentPeer which is one per window. All previous calls to repaint() would have invalidated rects in the window -this is managed by the OS. When the OS asks the window to be painted, these rects are recalled as the graphics context clip region, and passed through ComponentPeer::handlePaint() to the top Component’s paintEntireComponent() and then paintComponentAndChildren(). Here clipObscuredRegions() is called to exclude all opaque rects from the clip, and if something is left, paint() is called. Then this is done recursively for the whole hierarchy. If repaint() is called only on an opaque component, it should be excluded by clipObscuredRegions() making the clip empty, so the parent’s paint() wouldn’t be called (I’ve just checked this). But the OS may invalidate rects by itself for its own reasons. If your parent’s paint() is being called, either the system invalidated a region, or something not opaque is repainting, or something is calling repaint() on the parent.
If I recall, repainting a child component generates paint calls for the parent if any of the parent is visible to the left or right of that child component. For this reason, I try to structure my views to that they are divided into separate components consisting of horizontal bars that span the whole width of the plugin window, and then add child components to those bars that cover the entire height of their parent bar. That way, I’m only getting paint messages for the parent horizontal bar of the child component, not the whole window.