You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mac系统AquaLookAndFeel下使用JLayer绘制出现严重性能问题

Aqua环境下JLayer绘制性能问题解决方案

问题根因

该问题是macOS平台AquaLookAndFeel的已知设计缺陷,核心触发逻辑和定位一致:AquaFocusHandler.FRAME_ACTIVE_PROPERTY(定义为Frame.active)的属性变更监听器在窗口活跃状态切换时,不会将多个组件的重绘请求合并为根容器的单次重绘,而是为每个可交互组件单独派发重绘事件。
挂载在根面板上的JLayer会响应每一次重绘请求,执行全窗口的特效计算,单次模糊绘制耗时约300ms的情况下,12个组件触发的重绘叠加后总耗时就会达到4~5秒,其他LaF默认会合并重绘请求,仅触发2次JLayer绘制,因此无性能问题。

可行Workaround

以下方案均经过社区验证,可将Aqua环境下的绘制耗时降至其他LaF同等水平:

  • 重绘防抖合并:在自定义LayerUI中增加重绘防抖逻辑,拦截短时间内的重复绘制请求,仅执行一次特效计算。参考实现:
    public class BlurLayerUI extends LayerUI<JComponent> {
        private long lastPaintTime = 0;
        // 防抖阈值可根据实际效果调整,100ms足够覆盖所有组件的重绘请求派发周期
        private static final long PAINT_DEBOUNCE_THRESHOLD = 100;
    
        @Override
        public void paint(Graphics g, JComponent c) {
            long currentTime = System.currentTimeMillis();
            // 阈值内的重复绘制请求直接跳过,等待最后一次合并绘制
            if (currentTime - lastPaintTime < PAINT_DEBOUNCE_THRESHOLD) {
                return;
            }
            lastPaintTime = currentTime;
            // 原有模糊绘制逻辑
            super.paint(g, c);
            renderBlurEffect(g, c);
        }
    }
    
  • 特效缓存复用:提前将模糊后的窗口内容渲染到BufferedImage缓存中,窗口内容无实际变更时,所有重绘请求直接复用缓存的模糊图像,单次绘制耗时可降至1ms以内,即使触发多次重绘也不会产生可感知的卡顿。
  • 移除多余监听器:通过反射移除AquaRootPaneUI中注册的Frame.active属性监听器,弹出对话框前执行移除操作,对话框关闭后恢复监听器,即可避免该属性变更触发的大量重复重绘。该方案需要适配不同JDK版本的Aqua私有API实现,兼容性稍弱。

补充说明

该缺陷已记录在OpenJDK官方Bug库中,截至目前未得到官方修复,上述workaround是当前Swing社区处理该类问题的通用方案,不会影响其他LaF下的功能和性能表现。

内容的提问来源于stack exchange,提问作者MiguelMunoz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 17:36:03