Question

I have a JButton with an icon on it. I want the background color of the JButton to be the same as the icon.

The following code works fine in the standard look-and-feel :

button.setBackground(new Color(212,208,199));

But when I change my look-and-feel to Nimbus, then the background color of the JButton is much lighter.

The JButton still changes its background color when I change the color in button.setBackground(), but I have no idea to what color I need in Nimbus to get the same color as the background color of the JButton. Of course I could try to find the color by sight by trying all values, but there should be a simpler way.

I also tried changing the background color via the following code, but with the same result :

UIDefaults defaults = UIManager.getLookAndFeelDefaults();
defaults.put("Button.background",new Color(212,208,199));

How can I change the background color of my JButton in Nimbus, so that it merges with the background color of the containing icon ?

Below are some pictures of the button with default LaF, nimbus LaF (same code), and nimbus LaF (red color) :

Default LaF, using button.setBackground(new Color(212,208,199)) :

enter image description here

Nimbus LaF, using button.setBackground(new Color(212,208,199)) :

enter image description here

Nimbus LaF, using button.setBackground(Color.red) :

enter image description here

Was it helpful?

Solution 3

The question still ponders me, as I would like to know why nimbus changes the outcome of setBackground() ... I assume nimbus applies some kind of color mask, which slightly changes the colors slightly?

But : in my project the buttons are all in a separate JPanel, and the Jpanels which require the nimbus LaF don't have any buttons, so I solved the problem by using the default LaF for the buttons JPanel, and only use the nimbus LaF in the JPanels where I need it.

Sorry, that I didn't think of this before (I somehow assumed the LaF had to apply to the whole project).

So problem solved, but still curious to an answer about the nimbus color handling ....

OTHER TIPS

  1. please why Table.background use Button.background instead

  2. for more keys to see Nimbus Default

  3. more about Background for JButton in Nimbus

  4. maybe??? (no idea from your descriptions), maybe there no reason to change Background, have to look at JButtons API

methods

 JButton.setBorderPainted(false);
 JButton.setBorder(null);
 JButton.setFocusable(false);
 JButton.setMargin(new Insets(0, 0, 0, 0));
 JButton.setContentAreaFilled(false);
 JButton.setIcon(someIcon);
 JButton.setRolloverIcon(someIcon);
 JButton.setPressedIcon(someIcon);
 JButton.setDisabledIcon(someIcon);

Use an image with no transparency and the 'background' will be whatever color is in the BG of the image.

The icons are jpg files (with no transparency) but only fill a part of the whole button..

See this question for tips on how to get buttons that are the exact size of the icon. The image below is formed from 4 buttons and 5 labels with the icons cut from a single image.

..the text below the icon would still show the button background color..

Oh right. Text as well.

In that case, the best strategy is to create an image with a transparent BG from the existing image, then use it in whatever button (with whatever GB color) it comes.

To do that, get a PNG of the image (PNG is not lossy like JPG), and use a dedicated image editor to save it with a transparent BG. But if we are forced to do it at run-time, consider using something like this:

Image Background Cleaner

This image actually demonstrates the lossy nature of JPG. We have to go more & more 'distant' from the base BG color to try and pick up all pixels that are outside the original icon. Even at its loosest interpretation of similar color, I still see some spots I would prefer removed.

import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.imageio.ImageIO;
import java.net.URL;

class ImageBackgroundCleaner {

    public static BufferedImage clearImageBackground(BufferedImage solidBG, int distance) {
        int w = solidBG.getWidth();
        int h = solidBG.getHeight();
        BufferedImage transparentBG = new BufferedImage(
                w,
                h,
                BufferedImage.TYPE_INT_ARGB);
        int c = solidBG.getRGB(0, 0);
        for (int xx=0; xx<w; xx++) {
            for(int yy=0; yy<h; yy++) {
                int s = solidBG.getRGB(xx, yy);
                if (getColorDistance(s,c)>=distance) {
                    transparentBG.setRGB(xx, yy, s);
                }
            }
        }
        return transparentBG;
    }

    public static int getColorDistance(int color1, int color2) {
        Color c1 = new Color(color1);
        Color c2 = new Color(color2);
        int r1 = c1.getRed();
        int g1 = c1.getGreen();
        int b1 = c1.getBlue();
        int r2 = c2.getRed();
        int g2 = c2.getGreen();
        int b2 = c2.getBlue();

        return Math.abs(r1-r2) + Math.abs(g1-g2) + Math.abs(b1-b2);
    }

    public static void main(String[] args) throws Exception {
        URL url = new URL("http://i.stack.imgur.com/Yzfbk.png");
        BufferedImage bi = ImageIO.read(url);
        final BufferedImage img = bi.getSubimage(39, 21, 40, 40);
        Runnable r = new Runnable() {

            @Override
            public void run() {
                JPanel gui = new JPanel(new GridLayout(3,0,5,5));
                gui.setBackground(Color.RED);

                JLabel original = new JLabel(new ImageIcon(img));
                gui.add(original);

                int start = 12;
                int inc = 3;
                for (int ii=start; ii<start+(8*inc); ii+=inc) {
                    gui.add(new JLabel(new ImageIcon(clearImageBackground(img, ii))));
                }

                JOptionPane.showMessageDialog(null, gui);
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
        SwingUtilities.invokeLater(r);
    }
}
// you can always try this, it worked for me 
button.setContentAreaFilled(false);
button.setOpaque(true);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top