【问题标题】:Is there a way to only mark a specific JPanel region as opaque?有没有办法只将特定的 JPanel 区域标记为不透明?
【发布时间】:2011-12-31 19:34:04
【问题描述】:

基本上我画了很多透明的 JPanel;分析表明大部分时间都花在了 Component.paint() 中。可以彻底优化这一点,因为在大多数情况下,每个 JPanel 的真正非透明区域非常小,例如在边缘周围。

就目前而言,repainting() 组件将触发对其父级的 所有 的重绘,因为 RepaintManager 无法知道脏父级区域实际上是不透明的,并且会在组件上向上等级制度。我正在考虑在面板失效时向所有父母致电markCompletelyClean(),并自己使用addDirtyRegion()管理脏区。

但是,是否有一种更简洁的方法,仅将 JPanel 的特定矩形标记为不透明(或透明,无关紧要)?

【问题讨论】:

    标签: java swing jpanel repaint dirtyrectangle


    【解决方案1】:

    即使您对 markCompletelyClean() 和 addDirtyRegion() 做了一些花哨的事情,我怀疑您是否会获得很多性能优势。当 swing 进行重绘时,它会整理所有脏区域进行绘制,并使用所有脏区域的最小边界框开始重绘。因此,如果您将 JPanel 的周边标记为脏,则 JPanel 的边界框与整个 JPanel 相同,这意味着您将以任何方式重新绘制整个事物。

    【讨论】:

    • 但是,如果我将组件的 all 父组件标记为干净,它至少不会重新绘制它们,对吧?例如,因为我有一个非常大的非透明 JPanel 根,所以每次发生更改时都重新绘制它(以及导致它的所有内容)一定会对性能造成很大影响。
    • @PhilipK 他,这是一个有趣的问题,我猜你的问题的核心。 Java使用painters算法,意思是从后到前(父母到孩子)绘画,所以我真的看不出有什么方法可以让孩子在没有父母被吸引的情况下被绘画。但我并不十分了解 Java 的绘画算法,说这是不可能的。我们得去看看代码。您确定 addDirtyRegion() 不会将父母标记为脏吗?
    • 据我所知,如果孩子占用的矩形发生变化,则会将脏区域添加到父级,例如因为位置或大小的变化。我想当你有一个层次结构时会发生什么,比如说,5个透明面板并且最底部的孩子无效是他们都被重绘,因为理论上每个孩子像素都可能受到每个父母的影响,因为它们都是不透明的.但是如果我知道脏区实际上是不透明的,我可以在直接父节点处停止传播链。希望这是有道理的:)
    • @PhilipK 这是有道理的。我会着迷知道它是否有效。
    【解决方案2】:

    考虑使用JLabel(默认为非透明)而不是JPanel,然后您可以(到JLabel)添加任何JComponentJPanel 相同,但您有设置LayoutManager,那么你忘记关心Opacity/Transparency 和特定区域

    【讨论】:

    • 我不太明白。与使用 setOpaque(false) 的 JPanel 相比,JLabel 在性能方面究竟有哪些优势?
    【解决方案3】:

    为什么不能定义自己的方法myRepaint()调用多个

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

    所有的边界?

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

    【讨论】:

    • +1 我的问题不是更好地谈论 EDT 和paintImmediately,因为I'm drawing a lot of transparent JPanels
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-28
    • 1970-01-01
    • 2012-07-28
    • 2016-02-10
    • 2012-05-24
    • 2013-02-02
    • 2015-03-01
    相关资源
    最近更新 更多