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:

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
– Using Java™ Web Start (JRE 6 required)
Get The Code
Related Reading
Painting in AWT and Swing – Additional Paint Properties
Java API: java.awt.Color
Jeff said
Awesome. Exactly what I needed! Thank you very, very much!
Rob Camick said
Glad it solved your problem.
:)) said
Wohoo! Great, it works! :)
Rob Camick said
Nice to get such an enthusiastic response :)
:)) said
yeah, it was a long way until i found your blog post! ;-)
Jan Wehmeyer said
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?
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.
Jan Wehmeyer said
Thanks that worked. Great Job!
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);Chamz Dee said
Perfect..! Thank you very much :)
Rob Camick said
No problem. Glad it helped.
goctamhon said
Thank you! I’m looking for this :)
Rob Camick said
Glad you found what you where looking for.
Musa said
Reblogged this on A big picture of Hadi Waseem.
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.