1

Say I have ten JButtons each with their own background color explicitly set. Now, they all get the default mousepressed background color but how can I set it to be a shade darker of their respective background colors without doing it one by one?

I know that I can override the color in UIManager :

UIManager.put("Button.select", Color.RED);

Which I found here How to change a JButton color on mouse pressed?

But that will change it to a single color only. All of my buttons will get a red background when pressed.

Is there a way to make it something like:

UIManager.put("Button.select", JButton.getBackground().darker());

I'm trying to learn java swing so bear with my ignorance.

atan
  • 58
  • 2
  • 10
  • 1
    "Darker" is subjective based on the color you're starting with, which is why you would have to define each of your background colors and each of your "darker" colors. Once you've done that, then you could write the darker method in your example. – Gilbert Le Blanc Aug 08 '20 at 10:57
  • Does this answer your question? [How to change a JButton color on mouse pressed?](https://stackoverflow.com/questions/14627223/how-to-change-a-jbutton-color-on-mouse-pressed) – gthanop Aug 16 '20 at 21:29
  • @gthanop obviously not. It's the same link I provided above. – atan Aug 17 '20 at 04:42

1 Answers1

1

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.

gthanop
  • 3,035
  • 2
  • 10
  • 27
  • Perfect! Can't really see a huge visual difference between the two except that the `MetalButtonUI` solution has focusPainted but that's easy to work on. Thanks. – atan Aug 17 '20 at 04:42