Java Tips Weblog

  • Blog Stats

    • 1,252,364 hits
  • Categories

  • Archives

Backgrounds With Transparency

Posted by Rob Camick on May 31, 2009

Swing components allow you to change the background color of a component simply by using the setBackground() method. It is also possible to use a Color created with an “alpha” value. The alpha value defines the transparency of a Color. Unfortunately, once you start using alpha values in your background color you may encounter some undesireable painting artifacts.

To understand the problem we need to look at the setOpaque() method of Swing components. When the opaque value is:

  • true – The component agrees to paint all of the pixels contained within its rectangular bounds. This is done by painting the background before doing the custom painting of the component.
  • false – The component makes no guarantees about painting all the pixels within its rectangular bounds. Therefore the RepaintManager needs to do extra work. It needs to find an opaque ancestor of the component. Once it does, it then repaints the ancestor and all its children to make sure the rectangular bounds of the component is completely repainted.

Either way you are assured that all the pixels in the bounds of the component are painted every time the component is repainted.

So what happens when you introduce an alpha value in the background color of the component? Well, if the opaque value is

  • true – all the pixels are repainted, but because they are now transparent, you may see unexpected painting artifacts
  • false – the ancestor component and children are painted, but the components background is not painted so you lose the transparency effect.

Either way you don’t get the result you expect.

In the image below, the checkboxes are transparent and the panel uses a transparent background color. Everytime the mouse moves over a checkbox the transparency is reapplied resulting in an increasingly less transparent and darker background color:

Backgrounds-With-Transparency

The solution is to make sure the ancestor of the component is painted before the components background is painted. This is done in two steps:

  • first, the component is made non-opaque, by using setOpaque(false)
  • next, you add custom painting to the component to paint its background, by overriding the paintComponent() method. Note, when the alpha value is 0, then you can skip this step since the color is completely transparent so there is nothing to paint.

An example of applying the above two steps to a JPanel is shown below:

JPanel panel = new JPanel()
{
    protected void paintComponent(Graphics g)
    {
        g.setColor( getBackground() );
        g.fillRect(0, 0, getWidth(), getHeight());
        super.paintComponent(g);
    }
};
panel.setOpaque(false);
panel.setBackground( new Color(255, 0, 0, 20) );
frame.add(panel);

Eventually you may get tired of continually extending components to do this type of custom painting. Using the AlphaContainer class provides a reasonably easy workaround. It works by wrapping the transparent component and by doing the painting of the background using the components background color. The AlphaContainer will also manage the opaque property of the component. To use the AlphaContainer, the above code can be changed to:

JPanel panel = new JPanel();
panel.setBackground( new Color(255, 0, 0, 20) );
frame.add( new AlphaContainer(panel));

Next time you notice painting artifacts when using a transparent background Color try one of the above suggestions.

Note, an alpha value of 0 implies complete transparency which is equivalent to making the component non-opaque by using component.setOpaque(false). If complete transparency is your goal then make the component non-opaque instead of setting the background color to be transparent to take advantage of normal Swing painting. In the cases that you want to make a scrollpane transparent then you need to make the scrollpane, the viewport and the component all non-opaque.
 

Try The Demo

Launch – Using Java™ Web Start (JRE 6 required)

Get The Code

AlphaContainer.java

Related Reading

Painting in AWT and Swing – Additional Paint Properties
Java API: java.awt.Color

About these ads

24 Responses to “Backgrounds With Transparency”

  1. Jeff said

    Awesome. Exactly what I needed! Thank you very, very much!

  2. :)) said

    Wohoo! Great, it works! :)

  3. Works Great on a JEditorPane. But not when I put that JEditorPane in a ScrollPane.

    Anything Special I need to think of when I stack things?

    JEditorPane myEditorPane = new JEditorPane();
    myEditorPane.setBackground(new Color(0,0,0,0));
    myEditorPane.setOpaque(false);
    add(new AlphaContainer(myEditorPane);
    //until here it works.
    JScrollPane myScrollPane = new JScrollPane(new AlphaContainer(myEditorPane));
    myScrollPane.setBackground(new Color(0,0,0,0));
    myScrollPane.setOpaque(false);
    add(new AlphaContainer(myScrollPane));
    //works not
    
    • Rob Camick said

      An alpha value of 0, implies complete transparency so there is no need to set the background. All you need to do is make all the component non-opaque to take advantage of Swing painting. But you must do this for all components, the editor pane, the viewport and the scrollpane.

  4. prem ambodkar said

    its nice to set panel as transparent bt i also want to makes my tabbed pane invisible how can i do it???

    • Rob Camick said

      The UI for the tabbed pane controls this. You can override this property for the tabbed pane by using the following before creating the tabbed pane:

      UIManager.put("TabbedPane.contentOpaque", Boolean.FALSE);
      
  5. Chamz Dee said

    Perfect..! Thank you very much :)

  6. goctamhon said

    Thank you! I’m looking for this :)

  7. Musa said

    Reblogged this on A big picture of Hadi Waseem.

  8. Danniss10 said

    How does this work if you are painting directly onto a frame??

    • Rob Camick said

      You shouldn’t be painting directly onto a frame. You should do your custom painting on JPanel or JComponent and then add the panel to the frame. So I’m not sure how to answer your question.

  9. Anonymous said

    Thank you so much. This really helped. Well explained!

  10. Anonymous said

    Thank you so much this is really helpful . :)

  11. Final Kill said

    Windows 8 does not like this, because whenever I hover over the checkbox, it leaves the last thing that was hovered over by the mouse, resulting in a really buggy background, and many glitches.

  12. Danny said

    Thank you very much !!!!

  13. e7aso said

    Everythings work fine in case of using solid color as a background. I’m trying to use transparent image in background. I use paintComponent method and first I draw image with my background and then I call super.paintComponent(). Although I do these things I still get anoying white artifacts around JLabel text displaying on my JPanel with custom background. Is there something I do wrong?

    Here is my overrided paintComponent function in my JPane, which I simply set as a content pane in my JFrame.

    @Override
    public void paintComponent(Graphics g) {
          g.drawImage(my_png_image, 0, 0, null);
          super.paintComponent(g);
    }
    

    Additionaly I have set opaque of JPanel and JLabel to false.

    Please I really need help.

    • Rob Camick said

      Not sure I understand exactly what you are tying to do. The super.paintComponent() doesn’t do anything since you made the panel non-opaque, so the background does not get repainted. I would suggest that you check out the Alpha Icon blog entry. This will allow you to add a transparent Icon to a JLabel. Then you can use the label as a container just by setting the layout manager of the label. Now you can add other components to this label. If you have further questions, I suggest you try the forums, since this question doesn’t deal with the suggested solutions presented in this blog entry.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

Join 95 other followers

%d bloggers like this: