Search code examples
javaswingbackgroundjbuttonpaint

JButton background behavior isn't cleared


I'm trying to understand JButton behavior. When I am adding a button to JFrame with FlowLayout layout, then the button is displayed with some blue color, although when I call button.getBackground, I see that it returns a gray color (exactly the same RGB color as the JFrame-container background). I read that there is a method getContentAreaFilled that is also influence the button color.

If I set the contentAreaFilled to false, I really get a gray button. But,I also noticed that if I set button background to whatever color, then ContentAreaFilled color doesn't matter anymore. I want to understand how does it work? Why when the background color isn't changed (setBackground method isn't being called for button) the contentAreaFilled color is dominant over the background button color, and when JButton is set, the background is dominant over the contentAreaFilled color. Also setOpaque(false) method influence the button background color only if setBackground method was called, else setOpaque(false) doesn't do nothing and only ContentAreaFilled is matter

public class ButtonTest extends JFrame
{
   public static void main( String[] args )
   { 

      JButton justButton= new JButton("Just a Button");
    //  justButton.setBackground(Color.GREEN); //this line is critical
      System.out.println("Button color is:"+ justButton.getBackground()+"\n");
      ButtonTest frame= new ButtonTest();
      frame.setLayout(new FlowLayout());
      frame.add(justButton);
      frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
      frame.setSize( 275, 110 ); // set frame size
      frame.setVisible( true ); // display frame
      System.out.println("Frame background is:"+frame.getBackground()+"\n");
      System.out.println("getContentPane color 
       is:"+frame.getContentPane().getBackground()+"\n");
       System.out.println(justButton.isOpaque()+ "  " + 
        justButton.isContentAreaFilled());
   }
}

I expect that JBbutton color will be gray (with the default value of JButton background color) if I don't set button background differently. Also I expect that setOpaque method will influence JButton background to be transparent, regardless of setBackground method calls


Solution

  • The reason you are observing a "blue" color to your button is because of a gradient or other effect added by the pluggable look-and-feel (PLAF) in use. The color is actually grey, but the gradient makes it look blue. I'm guessing you are using the Metal PLAF, which has this effect.

    If you replace the button's UI by a non-PLAF UI:

    justButton.setUI((ButtonUI)BasicButtonUI.createUI(justButton));
    

    then the button will keep the default color without having to use setBackground or setContentAreaFilled.

    The reason calling setBackground has the effect of removing the gradient or other special effect is because individual LAFs deal differently with background colors. The Metal LAF removes the effect altogether. The windows system LAF practically ignores the background color, and only shows a thin border with the color. Note the documentation of JComponent.sebBackground:

    It is up to the look and feel to honor this property, some may choose to ignore it.

    enter image description here