Como alterar uma cor JButton no mouse pressionado?

Eu quero ter colors personalizadas de acordo com os events do mouse (o mouse entra, sai, pressionado, etc). Então, para conseguir isso, eu escrevi o código abaixo. Tudo bem, exceto no caso do evento pressionado pelo mouse, que não faz nada. Ele só funciona se eu replace a cor no UIManager como este UIManager.put("Button.select", Color.red); . Problema com o UIManager , é que vai mudar para todos os meus botões.

Alguém pode me dizer o que eu poderia estar fazendo errado ou qual é a melhor abordagem para realizar o que estou tentando fazer?

Meu Código:

 final JButton btnSave = new JButton("Save"); btnSave.setForeground(new Color(0, 135, 200).brighter()); btnSave.setHorizontalTextPosition(SwingConstants.CENTER); btnSave.setBorder(null); btnSave.setBackground(new Color(3, 59, 90)); btnSave.addMouseListener(new MouseListener() { @Override public void mouseReleased(MouseEvent e) { btnSave.setBackground(new Color(3, 59, 90)); } @Override public void mousePressed(MouseEvent e) { // Not working :( btnSave.setBackground(Color.pink); } @Override public void mouseExited(MouseEvent e) { btnSave.setBackground(new Color(3, 59, 90)); } @Override public void mouseEntered(MouseEvent e) { btnSave.setBackground(new Color(3, 59, 90).brighter()); } @Override public void mouseClicked(MouseEvent e) { btnSave.setBackground(new Color(3, 59, 90).brighter()); } }); 

Edit1: Então, ao invés de listener de mouse, eu estou usando ChangeListener e ButtonModel como sugerido por mKorbel. Com este código ainda não estou observando nenhuma alteração no mouse pressionado no botão, exceto quando pressiono e arraso para fora do botão. Alguma ideia?

 btnSave.getModel().addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { ButtonModel model = (ButtonModel) e.getSource(); if (model.isRollover()) { btnSave.setBackground(new Color(3, 59, 90).brighter()); } else if (model.isPressed()) { btnSave.setBackground(Color.BLACK); } else { btnSave.setBackground(new Color(3, 59, 90)); } } }); 

O problema é causado pelo fato de um JButton ter sua área de conteúdo preenchida por padrão e que o Metal L & F irá preenchê-lo automaticamente com sua cor escolhida interna quando o botão for pressionado.

A melhor coisa a fazer é estender o JButton para criar seu próprio botão, desabilitar a área de conteúdo preenchida e pintar você mesmo o plano de fundo do botão.

Aqui está uma pequena demonstração para isso (não tenho certeza se funciona em outras L & F, mesmo que tenha certeza que não funciona):

 import java.awt.Color; import java.awt.Graphics; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; public class TestButton { class MyButton extends JButton { private Color hoverBackgroundColor; private Color pressedBackgroundColor; public MyButton() { this(null); } public MyButton(String text) { super(text); super.setContentAreaFilled(false); } @Override protected void paintComponent(Graphics g) { if (getModel().isPressed()) { g.setColor(pressedBackgroundColor); } else if (getModel().isRollover()) { g.setColor(hoverBackgroundColor); } else { g.setColor(getBackground()); } g.fillRect(0, 0, getWidth(), getHeight()); super.paintComponent(g); } @Override public void setContentAreaFilled(boolean b) { } public Color getHoverBackgroundColor() { return hoverBackgroundColor; } public void setHoverBackgroundColor(Color hoverBackgroundColor) { this.hoverBackgroundColor = hoverBackgroundColor; } public Color getPressedBackgroundColor() { return pressedBackgroundColor; } public void setPressedBackgroundColor(Color pressedBackgroundColor) { this.pressedBackgroundColor = pressedBackgroundColor; } } protected void createAndShowGUI() { JFrame frame = new JFrame("Test button"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); final MyButton btnSave = new MyButton("Save"); btnSave.setForeground(new Color(0, 135, 200).brighter()); btnSave.setHorizontalTextPosition(SwingConstants.CENTER); btnSave.setBorder(null); btnSave.setBackground(new Color(3, 59, 90)); btnSave.setHoverBackgroundColor(new Color(3, 59, 90).brighter()); btnSave.setPressedBackgroundColor(Color.PINK); frame.add(btnSave); frame.setSize(200, 200); frame.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new TestButton().createAndShowGUI(); } }); } } 
  • nunca, não use MouseListener para JButton

  • use ActionListener ou ChangeListener com ButtonModel

  • no ButtonModel são implementados

    1) isPressed

    2) isArmed

    3) isRollover

    4) ei

  • exemplo para JButton & ButtonModel

 public class MyCustomButton extends JButton { private Color pressedColor = Color.GREEN; private Color rolloverColor = Color.RED; private Color normalColor = Color.BLUE; public MyCustomButton (String text) { super(text); setBorderPainted(false); setFocusPainted(false); setContentAreaFilled(false); setOpaque(true); setBackground(normalColor); setForeground(Color.WHITE); setFont(new Font("Tahoma", Font.BOLD, 12)); setText(text); addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent evt) { if (getModel().isPressed()) { setBackground(pressedColor); } else if (getModel().isRollover()) { setBackground(rolloverColor); } else { setBackground(normalColor); } } }); } } 

Poderia ser nada, mas poderia tentar usar em vez disso: Color.PINK, letras maiúsculas? Alguma mudança ao fazer isso?

Também não seria o mousepressed & mouseclicked replace um ao outro? mousepressed deve reagir quando você pressiona e clicado quando você libera a pressão do mouse

Em vez de definir a cor porque parece que não funciona, você pode tentar definir o plano de fundo em um arquivo de imagem extensível e defini-lo como plano de fundo. Isso poderia funcionar?

Tente isso com o que você já tem:

 yourButton.setBorder(null); yourButton.setContentAreaFilled(false);