Posted by Rob Camick on October 12, 2008
Many people want to know how to add a backgound image to a frame. The easiest way to do this is to add an image to a JLabel and then add the label to the frame. Is there a better way? Well, the answer depends on your requirements.
The code for this easy approach would be something like:
JLabel contentPane = new JLabel();
contentPane.setIcon( backgroundImage );
contentPane.setLayout( new BorderLayout() );
frame.setContentPane( contentPane );
Why does this work? Well, remember that all Swing components extend Container so you can add child components to them. However, by default, a JLabel uses a null layout so the components don’t appear. By using a BorderLayout the label can now function like a panel and be used as a content pane.
However, this approach has drawbacks, mostly because a label aways paints the image at it actual size. So in reality it would probably only be used on fixed size windows where the size of the window is determined by the size of the image.
In most other cases we need a more flexible approach, so we need a more flexible component. Introducing, BackgroundPanel, an extension of JPanel that provides some custom painting support for the drawing of images. The basic support provided by this class allows the images to be painted in one of 3 styles:
- scaled image (the default)
- tiled images
- actual sized image – the position of the image is controlled by specifying the horizontal and vertical alignment (center alignment is the default)
In addition to drawing images, this component can also be used to paint backgrounds that are not a solid colour. The Java API conveniently provides a Paint interface. A new setPaint(…) method was added to specify a Paint object to be used by the custom painting code. The Paint object can be used without an image. When both an image and a Paint object are used, the order of painting will be:
- paint the background
- paint using the Paint object
- draw the image
Also, the add(…) methods have been overridden to make each component added to the panel non-opaque. After all, if you are going to all the trouble to create a fancy background you dont want your opaque panel to block the custom painting. For components that use a renderer the renderer will also need to be transparent. For example, on a JTable, you can use the following to set the alpha value of the Color to 0, which results in a transparent background colour:
table.setBackground( new Color(0, 0, 0, 0) );
Following is the the code used to create the panel displayed in the attached image:
BackgroundPanel panel =
new BackgroundPanel(duke, BackgroundPanel.ACTUAL, 1.0f, 0.5f);
GradientPaint paint =
new GradientPaint(0, 0, Color.BLUE, 600, 0, Color.RED);