如何设置JButton被按下时的背景颜色?
问题根源在于Swing的默认ButtonUI会在按钮处于按下状态时,自动绘制系统自带的高亮背景,这会覆盖你通过setBackground()设置的颜色,所以你在mousePressed里设置的蓝色根本没机会显示出来。
下面给两种可行的解决方法:
方法一:手动绘制按钮背景(简单直接)
开启setContentAreaFilled(false)关闭系统默认的内容区域绘制,然后重写paintComponent方法自己控制背景颜色,这样就能完全摆脱系统UI的干扰。
修改后的完整代码:
import javax.swing.*; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class MyButton extends JButton { private final Color defaultColor = Color.RED; private final Color onClickColor = Color.BLUE; private boolean isPressed = false; // 记录按钮是否被按下 private String text; private String tier; public MyButton(String text, String tier, JFrame f) { this.text = text; this.tier = tier; setContentAreaFilled(false); // 开启这个,关闭系统默认绘制 setForeground(Color.WHITE); setBorderPainted(false); setFocusPainted(false); setText(text); addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { isPressed = true; repaint(); // 触发重绘,更新背景色 } @Override public void mouseReleased(MouseEvent e) { isPressed = false; repaint(); // 恢复默认背景 } // 处理鼠标移出按钮的情况,防止按住后移出不恢复颜色 @Override public void mouseExited(MouseEvent e) { if (isPressed) { isPressed = false; repaint(); } } }); // 调整按钮尺寸逻辑不变 if (tier.equals("Primary")) { setSize(f.getWidth()-14, 40); } else if (tier.equals("Secondary")) { setSize((text.length() * 10) + 10, 44); } } @Override protected void paintComponent(Graphics g) { // 先绘制背景 g.setColor(isPressed ? onClickColor : defaultColor); g.fillRect(0, 0, getWidth(), getHeight()); // 再调用父类方法绘制文字、图标等内容 super.paintComponent(g); } public static void main(String[] args) { JFrame f = new JFrame("frame"); f.setSize(400, 200); f.setLocationRelativeTo(null); f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); JPanel p = new JPanel(); p.setLayout(null); MyButton b = new MyButton("TESTTEST", "Primary", f); p.add(b); f.add(p); f.setVisible(true); } }
关键说明:
isPressed变量跟踪按钮状态,按下时设为true,松开/移出时设为falsepaintComponent里先根据isPressed绘制对应颜色的背景,再调用父类方法完成其他绘制- 增加
mouseExited处理,避免按住按钮时移出鼠标,背景一直停留在按下状态
方法二:自定义ButtonUI(更符合Swing规范)
如果想保留系统按钮的部分特性,也可以通过自定义UI类来重写状态绘制逻辑:
import javax.swing.*; import javax.swing.plaf.basic.BasicButtonUI; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class MyButton extends JButton { private final Color defaultColor = Color.RED; private final Color onClickColor = Color.BLUE; private String text; private String tier; public MyButton(String text, String tier, JFrame f) { this.text = text; this.tier = tier; setForeground(Color.WHITE); setBorderPainted(false); setFocusPainted(false); setText(text); // 设置自定义UI setUI(new CustomButtonUI(defaultColor, onClickColor)); // 不需要额外MouseListener,UI会处理状态 // 调整按钮尺寸逻辑不变 if (tier.equals("Primary")) { setSize(f.getWidth()-14, 40); } else if (tier.equals("Secondary")) { setSize((text.length() * 10) + 10, 44); } } // 自定义ButtonUI类 private static class CustomButtonUI extends BasicButtonUI { private final Color defaultColor; private final Color pressedColor; public CustomButtonUI(Color defaultColor, Color pressedColor) { this.defaultColor = defaultColor; this.pressedColor = pressedColor; } @Override public void paint(Graphics g, JComponent c) { AbstractButton button = (AbstractButton) c; // 根据按钮状态选择背景色 Color bgColor = button.getModel().isPressed() ? pressedColor : defaultColor; g.setColor(bgColor); g.fillRect(0, 0, button.getWidth(), button.getHeight()); // 调用父类绘制其他内容 super.paint(g, c); } } public static void main(String[] args) { JFrame f = new JFrame("frame"); f.setSize(400, 200); f.setLocationRelativeTo(null); f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); JPanel p = new JPanel(); p.setLayout(null); MyButton b = new MyButton("TESTTEST", "Primary", f); p.add(b); f.add(p); f.setVisible(true); } }
这个方法利用按钮自带的ButtonModel来获取状态,不需要自己维护isPressed变量,更符合Swing的设计模式。
内容的提问来源于stack exchange,提问作者Piacular
相关产品推荐
相关产品推荐

