如何在JFrame标题栏上放置自定义按钮
解决方案
问题根源
默认JFrame的标题栏属于系统级窗口装饰,不归Swing的内容面板管理。你直接添加到JFrame的组件都会被绘制在标题栏下方的客户区域,超出这个区域的部分会被默认裁剪,因此设置负y坐标的按钮会被标题栏遮挡。
实现思路
关闭系统默认窗口装饰,自行实现完整的标题栏UI,就可以自由在标题栏区域放置任意组件了。
修改后可运行代码
import javax.swing.*; import javax.swing.border.Border; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class SetBoundsTest { // 记录窗口拖动的坐标偏移 static int dragX, dragY; public static void main(String arg[]) { JFrame frame = new JFrame("Test Frame"); frame.setSize(500, 250); // 关闭系统默认装饰 frame.setUndecorated(true); frame.setLayout(new BorderLayout()); // 自定义标题栏面板 JPanel titleBar = new JPanel(new BorderLayout()); titleBar.setPreferredSize(new Dimension(frame.getWidth(), 35)); titleBar.setBackground(Color.LIGHT_GRAY); Border border = BorderFactory.createMatteBorder(0, 0, 1, 0, Color.GRAY); titleBar.setBorder(border); // 标题文字 JLabel titleLabel = new JLabel(" Test Frame"); titleBar.add(titleLabel, BorderLayout.WEST); // 你要添加的自定义按钮 JButton customBtn = new JButton("Test"); customBtn.setBorder(BorderFactory.createLineBorder(Color.BLUE, 3)); customBtn.setBackground(Color.MAGENTA); customBtn.setPreferredSize(new Dimension(120, 30)); // 放到标题栏中间 JPanel btnPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 2)); btnPanel.setOpaque(false); btnPanel.add(customBtn); titleBar.add(btnPanel, BorderLayout.CENTER); // 右上角关闭按钮,模拟系统功能 JButton closeBtn = new JButton("×"); closeBtn.setPreferredSize(new Dimension(50, 35)); closeBtn.setBorderPainted(false); closeBtn.setFocusPainted(false); closeBtn.setBackground(Color.LIGHT_GRAY); closeBtn.addActionListener(e -> System.exit(0)); // 鼠标悬停变红 closeBtn.addMouseListener(new MouseAdapter() { @Override public void mouseEntered(MouseEvent e) { closeBtn.setBackground(Color.RED); closeBtn.setForeground(Color.WHITE); } @Override public void mouseExited(MouseEvent e) { closeBtn.setBackground(Color.LIGHT_GRAY); closeBtn.setForeground(Color.BLACK); } }); titleBar.add(closeBtn, BorderLayout.EAST); // 实现窗口拖动功能 titleBar.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { dragX = e.getX(); dragY = e.getY(); } }); titleBar.addMouseMotionListener(new MouseAdapter() { @Override public void mouseDragged(MouseEvent e) { frame.setLocation(frame.getX() + e.getX() - dragX, frame.getY() + e.getY() - dragY); } }); // 把标题栏添加到窗口顶部 frame.add(titleBar, BorderLayout.NORTH); // 剩下的内容区域你可以自己加其他组件 JPanel contentPane = new JPanel(); contentPane.setBackground(Color.WHITE); frame.add(contentPane, BorderLayout.CENTER); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationRelativeTo(null); frame.setVisible(true); } }
效果说明
上述代码完全自定义了标题栏,不仅可以实现你需要的在标题栏中间放置按钮的效果,还保留了窗口拖动、关闭的基础功能,你可以根据自己的需求调整标题栏的样式、按钮的位置和功能。
内容的提问来源于stack exchange,提问作者Kather
相关产品推荐
相关产品推荐

