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

如何移除Java Swing中JFrame装饰的关闭按钮(保留最小化/最大化按钮)

移除JFrame关闭按钮但保留其他窗口装饰的实现方案

Swing没有标准API能直接单独隐藏系统提供的关闭按钮,以下是两种可行方案:

方法一:自定义窗口装饰(跨平台通用)

使用无装饰窗口(setUndecorated(true)),自行实现标题栏、最小化/最大化按钮及窗口拖动功能,完全控制窗口装饰的显示,自然就能去掉关闭按钮。

示例代码:

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class CustomTitleBarFrame extends JFrame {
    private int dragStartX, dragStartY;

    public CustomTitleBarFrame() {
        setUndecorated(true);
        setSize(600, 400);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        // 自定义标题栏
        JPanel titleBar = new JPanel(new BorderLayout());
        titleBar.setBackground(Color.DARK_GRAY);

        // 标题文本
        JLabel titleLabel = new JLabel("自定义窗口");
        titleLabel.setForeground(Color.WHITE);
        titleLabel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 0));
        titleBar.add(titleLabel, BorderLayout.WEST);

        // 操作按钮面板
        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 0, 0));
        buttonPanel.setBackground(Color.DARK_GRAY);

        // 最小化按钮
        JButton minimizeBtn = new JButton("-");
        styleButton(minimizeBtn);
        minimizeBtn.addActionListener(e -> setState(ICONIFIED));
        buttonPanel.add(minimizeBtn);

        // 最大化按钮
        JButton maximizeBtn = new JButton("□");
        styleButton(maximizeBtn);
        maximizeBtn.addActionListener(e -> {
            if (getExtendedState() == MAXIMIZED_BOTH) {
                setState(NORMAL);
                maximizeBtn.setText("□");
            } else {
                setState(MAXIMIZED_BOTH);
                maximizeBtn.setText("▢");
            }
        });
        buttonPanel.add(maximizeBtn);

        // 不添加关闭按钮,实现移除需求
        titleBar.add(buttonPanel, BorderLayout.EAST);

        // 标题栏拖动功能
        titleBar.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                dragStartX = e.getX();
                dragStartY = e.getY();
            }
        });
        titleBar.addMouseMotionListener(new MouseAdapter() {
            @Override
            public void mouseDragged(MouseEvent e) {
                setLocation(getX() + e.getX() - dragStartX, getY() + e.getY() - dragStartY);
            }
        });

        // 组装窗口
        add(titleBar, BorderLayout.NORTH);
        JPanel contentPanel = new JPanel();
        contentPanel.add(new JLabel("窗口内容"));
        add(contentPanel, BorderLayout.CENTER);

        setVisible(true);
    }

    private void styleButton(JButton btn) {
        btn.setForeground(Color.WHITE);
        btn.setBackground(Color.DARK_GRAY);
        btn.setBorder(BorderFactory.createEmptyBorder(5, 15, 5, 15));
        btn.setFocusPainted(false);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(CustomTitleBarFrame::new);
    }
}

方法二:Windows平台专用(修改原生窗口样式)

如果应用仅需在Windows环境运行,可以通过JNI调用Windows API修改窗口样式位,直接隐藏原生关闭按钮,保留其他系统装饰。

示例代码:

import javax.swing.*;
import java.lang.reflect.Method;

public class WindowsOnlyFrame extends JFrame {
    // Windows API 常量
    private static final int GWL_STYLE = -16;
    private static final int WS_SYSMENU = 0x00080000;
    private static final int WS_MINIMIZEBOX = 0x00020000;
    private static final int WS_MAXIMIZEBOX = 0x00010000;

    public WindowsOnlyFrame() {
        setTitle("Windows原生窗口");
        setSize(600, 400);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);

        modifyWindowDecoration();
    }

    private void modifyWindowDecoration() {
        try {
            // 通过反射获取窗口句柄
            Method getPeer = JFrame.class.getDeclaredMethod("getPeer");
            getPeer.setAccessible(true);
            Object peerObj = getPeer.invoke(this);
            Method getHWnd = peerObj.getClass().getDeclaredMethod("getHWnd");
            getHWnd.setAccessible(true);
            long hwnd = (long) getHWnd.invoke(peerObj);

            // 调用Windows API修改样式
            System.loadLibrary("user32");
            long currentStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
            // 保留最小化、最大化按钮,移除系统菜单(关闭按钮属于系统菜单的一部分)
            long newStyle = currentStyle & ~WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
            SetWindowLongPtr(hwnd, GWL_STYLE, newStyle);
            // 更新窗口外观
            SetWindowPos(hwnd, 0, 0, 0, 0, 0, 0x0001 | 0x0002 | 0x0004 | 0x0010);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // Native方法声明
    private native long GetWindowLongPtr(long hwnd, int nIndex);
    private native long SetWindowLongPtr(long hwnd, int nIndex, long dwNewLong);
    private native boolean SetWindowPos(long hwnd, long hWndInsertAfter, int x, int y, int cx, int cy, int uFlags);

    public static void main(String[] args) {
        SwingUtilities.invokeLater(WindowsOnlyFrame::new);
    }
}

注意:该方案依赖Windows原生API,跨平台运行会抛出异常,需要编译对应的JNI动态链接库才能正常工作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 19:09:55