4

Basically I'm drawing a lot of transparent JPanels; profiling shows that most time is spent in Component.paint(). It would be possible to optimize this quite radically since in most cases the real non-opaque area per JPanel is quite small, for example around the edges.

As it stands now, repainting() a component would trigger a repaint of all its parents, since the RepaintManager can't know the dirty parent area is in fact opaque and will go up the component hierarchy. I was thinking about calling markCompletelyClean() on all parents whenever a panel is invalidated and managing the dirty regions myself with addDirtyRegion().

However, is there a cleaner approach of marking only specific rectangles of a JPanel as opaque (or transparent, doesn't matter)?

Philip Kamenarsky
  • 2,757
  • 2
  • 24
  • 30

3 Answers3

2

Even if you do something fancy with markCompletelyClean() and addDirtyRegion(), I doubt you'll get much of a performance benefit. When swing goes for a repaint, it collates all of the dirty regions to paint and starts a repaint with the minimum bounding box of all of the dirty regions. Thus if you mark the perimeter of a JPanel as dirty, then the bounding box of the JPanel is the same as the entire JPanel, which means you'll be repainting the entire thing any way.

heneryville
  • 2,853
  • 1
  • 23
  • 30
  • But at least it wouldn't repaint *all* parents of a component if I mark them as clean, right? Since, for example, I have a pretty big root non-opaque JPanel, redrawing it (and everything leading up to it) every time something changes must be quite a performance hit. – Philip Kamenarsky Nov 17 '11 at 23:09
  • @PhilipK Him, that's an interesting question, and I guess the heart of your question. Java uses the painters algorithm, meaning to paints from back to front (parent to child), so I really don't see any way for a child to get drawn without its parent getting drawn to. But I'm not THAT intimately aware of Java's painting algorithm to say it's impossible. We'd have to go look at the code. Are you sure addDirtyRegion() doesn't mark the parents as dirty? – heneryville Nov 18 '11 at 01:52
  • From what I gather, a dirty region is added to the parent if the rect occupied by a child changes, e.g. because of a position or size change. I guess what happens though when you have a hierarchy of, let's say, 5 transparent panels and the bottom-most child gets invalidated is that they ALL get redrawn since every child pixel could theoretically be affected by every parent since they are all non-opaque. But if I know the dirty region is in fact opaque, I couls stop the propagation chain at the immediate parent. Hope that makes sense :) – Philip Kamenarsky Nov 18 '11 at 04:38
  • @PhilipK It makes sense. I'd be **fascinated** to know if it works. – heneryville Nov 18 '11 at 04:41
2

Consider using JLabel (non-opaque by default) instead of JPanel, then you are able (to the JLabel) you can add any JComponent same as to the JPanel, but you have to set LayoutManager, then you forgot care about Opacity/Transparency and for particulars Region(s)

mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • 1
    I don't quite understand. What exactly are the benefits of a JLabel in terms of performance compared to a JPanel with setOpaque(false)? – Philip Kamenarsky Nov 17 '11 at 23:13
1

Why can't you define your own method myRepaint() calling multiple

public void repaint(long tm, int x, int y, int width, int height)

for all the borders?

Also try to play with clipBounds of your Graphics to repaint only really necessary parts. You can set any custom Shape as clip.

StanislavL
  • 56,971
  • 9
  • 68
  • 98
  • +1 my question isn't there better talking about EDT & paintImmediately, because `I'm drawing a lot of transparent JPanels` – mKorbel Nov 18 '11 at 05:59