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

如何重写JFrame的setUndecorated方法?L&F开发圆角窗口适配

解决方案

1. 优化顶层JFrame的获取方式

直接通过rootPane.getParent()获取JFrame不可靠,因为JRootPane的直接父容器可能不是顶层窗口。应该使用SwingUtilities.getWindowAncestor()来获取顶层窗口,再判断是否为JFrame:

@Override
public void installUI(JComponent component) {
    super.installUI(component);
    JRootPane rootPane = (JRootPane) component;
    Window window = SwingUtilities.getWindowAncestor(rootPane);
    
    if (window instanceof JFrame) {
        JFrame frame = (JFrame) window;
        // 后续处理逻辑
    }
}

2. 拦截setUndecorated调用,保证窗口始终为无装饰状态

Java无法直接重写已有实例的方法,我们可以通过监听undecorated属性变化来强制保持窗口的无装饰状态,同时避免循环调用:

private boolean isUpdatingUndecorated = false;

@Override
public void installUI(JComponent component) {
    super.installUI(component);
    JRootPane rootPane = (JRootPane) component;
    Window window = SwingUtilities.getWindowAncestor(rootPane);
    
    if (window instanceof JFrame) {
        JFrame frame = (JFrame) window;
        
        // 初始设置为无装饰状态
        if (!frame.isUndecorated()) {
            frame.setUndecorated(true);
        }
        // 应用圆角形状
        updateRoundCornerShape(frame);
        
        // 监听undecorated属性变化,拦截外部修改
        frame.addPropertyChangeListener("undecorated", evt -> {
            if (isUpdatingUndecorated) return;
            
            boolean newValue = (boolean) evt.getNewValue();
            if (!newValue) {
                isUpdatingUndecorated = true;
                try {
                    frame.setUndecorated(true);
                    updateRoundCornerShape(frame);
                } finally {
                    isUpdatingUndecorated = false;
                }
            }
        });
        
        // 监听窗口大小变化,更新圆角形状
        frame.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                updateRoundCornerShape(frame);
            }
        });
    }
}

// 封装圆角形状设置逻辑
private void updateRoundCornerShape(JFrame frame) {
    int cornerRadius = 20; // 可根据需求调整圆角半径
    frame.setShape(new RoundRectangle2D.Double(0, 0, frame.getWidth(), frame.getHeight(), cornerRadius, cornerRadius));
}

说明

  • 通过PropertyChangeListener拦截外部对setUndecorated(false)的调用,强制恢复为无装饰状态,避免破坏圆角UI。
  • 添加ComponentListener监听窗口大小变化,实时更新圆角形状,防止窗口缩放后圆角失效。
  • 使用SwingUtilities.getWindowAncestor()能可靠获取顶层窗口,适配更复杂的容器嵌套场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:21:26