How to Change a Jbutton Color on Mouse Pressed

How to change a JButton color on mouse pressed?

The problem is caused by the fact that a JButton has its content area filled by default and that the Metal L&F will automatically fill it with its internal chosen color when button is pressed.

Best thing to do, is to extend JButton to create your own button, disable content area filled, and paint yourself the background of the button.

Here is a small demo for that (not sure it works on other L&F, even pretty sure it does not):

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();
}
});

}

}

Change JButton's click color?

change color of button text using setForeground method

like this

        @Override
public void mousePressed(MouseEvent e) {
b.setForeground(Color.red); // button text color
// b.setBackground(Color.red); // button background color
}

@Override
public void mouseReleased(MouseEvent e) {
b.setForeground(Color.black); // button text color
}

How to change the background color of a Jbutton on click

If you want to change the background of the button with a persistent color when the user clicks on the button, then you can use setContentAreaFilled(false) on it. Then it is required to reset the opaque property to true because according to the docs of setContentAreaFilled: "This function may cause the component's opaque property to change.", for example:

import java.awt.Color;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class MainPersist {

private static void createAndShowGUI() {
final JButton button = new JButton("Click to change color");
button.addActionListener(e -> {
button.setContentAreaFilled(false);
button.setOpaque(true); //Reset the opacity.
button.setBackground(Color.CYAN.darker()); //Set your desired color as the background.
});

final JFrame frame = new JFrame("Button bg on click");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(button);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

public static void main(final String[] args) {
SwingUtilities.invokeLater(MainPersist::createAndShowGUI);
}
}

Otherwise, if you want the button to only change its color when clicked and then return back to normal when released, then take a look at this question which is about exactly that. It has no accepted answers yet (it is very recent as of the time this answer itself is posted), but there is at least one/my answer (which suggests to modify the ButtonUI of the button) and there should be more answers coming I guess.

How to change a JButton color when I hover over it but change it permanently to something else even if I hover afterwards when I click it?

Sounds like you want the button to stay yellow, until clicked again?

Try this:

public void mouseEntered(MouseEvent e) {
if (bakery.getBackground() != Color.YELLOW) { // skip if already yellow
bakery.setBackground(Color.GREEN);
}
}

public void mouseExited(MouseEvent e) {
if (bakery.getBackground() != Color.YELLOW) { // skip if already yellow
bakery.setBackground(UIManager.getColor("control"));
}
}

public void mousePressed(MouseEvent e) {
if (bakery.getBackground() != Color.YELLOW) {
// The first click will set yellow
bakery.setBackground(Color.YELLOW);
} else {
// A second click clears the yellow.
bakery.setBackground(UIManager.getColor("control"));
}
}

How can I override the default mousepressed background color of all JButtons into a darker shade of its current background color?

One way to do this, is to create your own ButtonUI. To avoid the hassle of reinventing the wheel, you can exend a subclass of ButtonUI.

For example BasicButtonUI like so:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.util.Objects;
import java.util.Random;
import javax.swing.AbstractButton;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.plaf.basic.BasicButtonUI;

public class MainWithBasicButtonUI {

public static class SelectButtonUI extends BasicButtonUI {
protected Color selectColor;

public void setSelectColor(final Color selectColor) {
this.selectColor = Objects.requireNonNull(selectColor);
}

public Color getSelectColor() {
return selectColor;
}

@Override
protected void paintButtonPressed(final Graphics g,
final AbstractButton b){
if (b.isContentAreaFilled()) {
Dimension size = b.getSize();
g.setColor(getSelectColor());
g.fillRect(0, 0, size.width, size.height);
}
}
}

private static void createAndShowGUI() {
final int rows = 3, cols = 3;
final Color[] colors = new Color[]{Color.RED.brighter(), Color.GREEN.brighter(), Color.CYAN};
final JPanel buttons = new JPanel(new GridLayout(rows, cols, 2, 2));
final Random rand = new Random();
for (int i = 0; i < rows * cols; ++i) {
final JButton b = new JButton("Button");
b.setBackground(colors[rand.nextInt(colors.length)]);
final SelectButtonUI ui = new SelectButtonUI();
ui.setSelectColor(b.getBackground().darker());
b.setUI(ui);
buttons.add(b);
}
final JFrame frame = new JFrame("App");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(buttons);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

public static void main(final String[] args) {
SwingUtilities.invokeLater(MainWithBasicButtonUI::createAndShowGUI);
}
}

or, even better, MetalButtonUI like so:

import java.awt.Color;
import java.awt.GridLayout;
import java.util.Objects;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.plaf.metal.MetalButtonUI;

public class MainWithMetalButtonUI {

public static class SelectButtonUI extends MetalButtonUI {
public SelectButtonUI() {
selectColor = super.getSelectColor();
}

public void setSelectColor(final Color selectColor) {
this.selectColor = Objects.requireNonNull(selectColor);
}

@Override
protected Color getSelectColor() {
return selectColor;
}
}

private static void createAndShowGUI() {
final int rows = 3, cols = 3;
final Color[] colors = new Color[]{Color.RED.brighter(), Color.GREEN.brighter(), Color.CYAN};
final JPanel buttons = new JPanel(new GridLayout(rows, cols, 2, 2));
final Random rand = new Random();
for (int i = 0; i < rows * cols; ++i) {
final JButton b = new JButton("Button");
b.setBackground(colors[rand.nextInt(colors.length)]);
final SelectButtonUI ui = new SelectButtonUI();
ui.setSelectColor(b.getBackground().darker());
b.setUI(ui);
buttons.add(b);
}
final JFrame frame = new JFrame("App");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(buttons);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

public static void main(final String[] args) {
SwingUtilities.invokeLater(MainWithMetalButtonUI::createAndShowGUI);
}
}

The only problem with this, is that all your buttons are always going to look like in the metal L&F.

I don't want to change color of JButton when pressed

I've found nothing that can change that particular behavior on a normal JButton. The problem being, that whatever you write in your actionlistener for the button, will occur AFTER you've let go of the mousebutton, and not "while clicking".

There are workarounds, however.

My preferred choice is, to remove all graphics from the button, and then add your own images to the button's regular and pressed states. You could take a screenshot of your GUI, cut out the button, and set that image to be both states.

JButton myButton = new JButton();

// Sets button x, y, width, height. Make the size match the image.
myButton.setBounds(5, 30, 100, 30);

// Remove border-graphics.
myButton.setBorder(null);

// Remove default graphics from the button
myButton.setContentAreaFilled(false);

// Remove the focus-indicating dotted square when focused (optional)
myButton.setFocusPainted(false);

// Here, myImage is a simple BufferedImage object.
// You can set one like this, provided you have an "images" package,
// next to your main class (ex: com.somecompany.someprogram.images),
// that contains an image:

BufferedImage myImage = ImageIO.read(getClass().getResource("images/myImage.png"));

// Then we simply apply our image to both states for the button, and we're done.
myButton.setIcon(new ImageIcon(myImage));

myButton.setPressedIcon(new ImageIcon(myImage));

Obviously there are many ways to retain and load an image, but since that's not the issue here, I'll leave additional methods out of it.

There's no need to go through it all countless times, though. It should be pretty easy to write your own custom implementation of the JButton class, in which a custom constructor takes a single parameter, being the BufferedImage, and then the constructor sets it up accordingly (changes the icons). Then all you have to do when you create a new JButton, is to use your own class, and pass it an image:

JButton btn = new MyCustomJButton(myImage);

You could also easily get along with very few images. All you need is a HashMap which holds all the images, with a String as a key. Imagine you need 4 OK-buttons. You make a single image of a button with the text "OK" written on it. Then you put that image into the HashMap, like so:

myMap.put("OK", myImage);

Then you could do this when creating a button, over and over again if you'd like more:

JButton btn = new MyCustomJButton(myMap.get("OK"));

Alternatively:
Another way of achieving this, which is pretty elaborate, but probably considered "the right way", is to use ButtonUI, as presented in this answer to another post.

How to change Background color when i click a button

You're on the right track, but you need to tie the events to the button components rather than the interrupt signals of the mouse.

Instead of a MouseListener, change theHandler to this:

  public class TheActionHandler implements ActionListener {

@Override
public void actionPerformed(final ActionEvent e) {
if(e.getSource()==bred)
{
mousepanel.setBackground(Color.red);
}

else if(e.getSource()==bblue)
{
mousepanel.setBackground(Color.blue);
}

else if(e.getSource()==bgreen)
{
mousepanel.setBackground(Color.green);
}
}
}


Related Topics



Leave a reply



Submit