有没有方法只将特定的JPanel区域标记为不透明?

4
基本上,我正在绘制许多透明的JPanels;分析显示大部分时间都花费在Component.paint()上。在大多数情况下,每个JPanel的真正非不透明区域相当小,例如在边缘周围。
现在的情况是,重新绘制组件会触发其所有父项的重绘,因为RepaintManager无法知道脏父项区域实际上是不透明的并且会向上遍历组件层次结构。我考虑在面板失效时对所有父项调用markCompletelyClean(),并使用addDirtyRegion()自己管理脏区域。
然而,有没有更清晰的方法来标记JPanel的特定矩形区域为不透明(或透明,不重要)?
3个回答

2
即使您使用markCompletelyClean()和addDirtyRegion()进行高级操作,我也怀疑您会获得很大的性能提升。当Swing进行重绘时,它会整理所有需要绘制的脏区域,并从所有脏区域中计算出最小边界框来开始重绘。因此,如果将JPanel的周围标记为脏区域,则JPanel的边界框与整个JPanel相同,这意味着您无论如何都将重绘整个组件。

但是如果我将它们标记为干净,那么它至少不会重新绘制组件的所有父级,对吧?例如,我有一个相当大的根非透明JPanel,每次更改时重新绘制它(以及一切向上的内容)必须会对性能产生相当大的影响。 - Philip Kamenarsky
@PhilipK 那是一个有趣的问题,也是你问题的核心。Java使用画家算法,从后往前绘制(从父级到子级),所以我真的看不出子级在没有父级被绘制的情况下被绘制的任何可能性。但我并不是那么熟悉Java的绘图算法,不能说这是不可能的。我们需要去查看代码。你确定addDirtyRegion()不会标记父级为脏吗? - heneryville
据我所知,如果子元素占用的矩形发生变化(例如位置或大小更改),则会将脏区添加到父级。但是,如果您有一个层次结构,比如说,5个透明面板,并且最底部的子元素被使无效了,那么它们全部都会被重绘,因为每个父元素都可能受到每个子像素的影响,因为它们都是非不透明的。但是,如果我知道脏区实际上是不透明的,我可以在直接父级处停止传播链。希望这有意义 :) - Philip Kamenarsky
@PhilipK 有道理。如果它能够运行,我会非常着迷知道的。 - heneryville

2
考虑使用默认非透明的JLabel代替JPanel,这样你就可以像添加到JPanel一样添加任何JComponent到JLabel中。但是你需要设置LayoutManager,然后就不再需要考虑透明度和特定区域的问题了。

1
我不太明白。与设置setOpaque(false)的JPanel相比,JLabel在性能方面到底有哪些优势? - Philip Kamenarsky

1
为什么不能定义自己的方法myRepaint()并调用多个?
public void repaint(long tm, int x, int y, int width, int height)

对于所有的边框?

同时尝试使用图形的clipBounds来仅重新绘制真正必要的部分。您可以将任何自定义形状设置为剪辑。


+1 我的问题是不是有更好的谈论EDT和paintImmediately,因为我正在绘制许多透明的JPanels。 - mKorbel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接