Java Swing 圆形JButton鼠标悬停后出现无法消失的方形背景问题
问题描述
我在使用Java Swing开发时,只要将鼠标悬停在任意圆形按钮上,按钮后方就会出现一块方形背景且再也不会消失。按钮本身仍可正常点击,但该方形背景无交互响应。我没有实现任何鼠标事件,不清楚这块背景出现的原因。

左:点击后状态,中:鼠标悬停后状态,右:初始状态
完整代码示例
import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.*; public class GUI implements ActionListener { private JLabel textLabel; private JButton buttonL, buttonConfirm, buttonR; public GUI() { JPanel mainDisplay = new JPanel(); mainDisplay.setBackground(new Color(172, 181, 176)); mainDisplay.setPreferredSize(new Dimension(150, 160)); mainDisplay.setLayout(new BorderLayout()); textLabel = new JLabel("1"); textLabel.setHorizontalAlignment(SwingConstants.CENTER); mainDisplay.add(textLabel, BorderLayout.CENTER); JPanel container = new JPanel(); container.setLayout(new GridBagLayout()); GridBagConstraints gc = new GridBagConstraints(); gc.gridwidth = GridBagConstraints.REMAINDER; gc.insets = new Insets(75, 0, 0, 0); container.add(mainDisplay, gc); Dimension buttonDimension = new Dimension(18, 18); Color buttonColor = new Color(242, 240, 241); buttonL = new RoundButton(); buttonL.setBackground(buttonColor); buttonL.setPreferredSize(buttonDimension); buttonL.addActionListener(this); gc.gridwidth = GridBagConstraints.RELATIVE; gc.insets = new Insets(10, 20, 0, 0); container.add(buttonL, gc); buttonConfirm = new RoundButton(); buttonConfirm.setBackground(buttonColor); buttonConfirm.setPreferredSize(buttonDimension); buttonConfirm.addActionListener(this); gc.insets = new Insets(40, -35, 0, 0); container.add(buttonConfirm, gc); buttonR = new RoundButton(); buttonR.setBackground(buttonColor); buttonR.setPreferredSize(buttonDimension); buttonR.addActionListener(this); gc.insets = new Insets(10, -50, 0, 0); container.add(buttonR, gc); JFrame frame = new JFrame(); frame.add(container); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } @Override public void actionPerformed(ActionEvent e) { if(e.getSource() == buttonL) { textLabel.setText("L"); } else if(e.getSource() == buttonConfirm) { textLabel.setText(""); } else if(e.getSource() == buttonR) { textLabel.setText("R"); } } public static void main(String[] args) { new GUI(); } }
原圆形JButton实现代码
import java.awt.Color; import java.awt.Graphics; import java.awt.Shape; import java.awt.geom.Ellipse2D; import javax.swing.JButton; public class RoundButton extends JButton { Shape shape; @Override protected void paintComponent(Graphics g) { g.setColor(getBackground()); g.fillOval(0, 0, getSize().width - 1, getSize().height - 1); } @Override protected void paintBorder(Graphics g) { g.setColor(Color.darkGray); g.drawOval(0, 0, getSize().width - 1, getSize().height - 1); } @Override public boolean contains(int x, int y) { if (shape == null || !shape.getBounds().equals(getBounds())) { shape = new Ellipse2D.Float(0, 0, getWidth(), getHeight()); } return shape.contains(x, y); } }
解决方案
问题根因
Swing默认JButton为不透明组件,交互(悬停、获焦)时UI代理会自动绘制默认的方形背景,你自定义重写paintComponent时没有清除原有区域内容,也没有关闭默认的背景绘制逻辑,导致方形背景绘制后残留无法消失。
修复后的RoundButton代码
import java.awt.Color; import java.awt.Graphics; import java.awt.Shape; import java.awt.geom.Ellipse2D; import javax.swing.JButton; public class RoundButton extends JButton { Shape shape; public RoundButton() { // 关闭默认不透明填充,禁止UI自动绘制方形背景 setOpaque(false); // 关闭默认焦点框绘制,避免点击后出现方形焦点边框 setFocusPainted(false); // 关闭内容区域自动填充,适配不同观感实现,避免多余绘制 setContentAreaFilled(false); } @Override protected void paintComponent(Graphics g) { g.setColor(getBackground()); g.fillOval(0, 0, getSize().width - 1, getSize().height - 1); // 后续如果需要给按钮添加文字、图标,保留下方super调用即可,无内容可删除 super.paintComponent(g); } @Override protected void paintBorder(Graphics g) { g.setColor(Color.darkGray); g.drawOval(0, 0, getSize().width - 1, getSize().height - 1); } @Override public boolean contains(int x, int y) { if (shape == null || !shape.getBounds().equals(getBounds())) { shape = new Ellipse2D.Float(0, 0, getWidth(), getHeight()); } return shape.contains(x, y); } }
修改后重新运行即可消除悬停残留的方形背景。
内容的提问来源于stack exchange,提问作者Egg
相关产品推荐
相关产品推荐

