如何移除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
相关产品推荐
相关产品推荐

