|
Displaying Background Images with Swing
When figuring out how to display background images, it quickly becomes apparent that the primary issue is enabling transparency in any foreground objects, so that the container background can show through. Swing's JComponents, being exclusively lightweights, are drawn using their container's graphics and generally default to false for isOpaque(). The net effect is automatic transparency for most JComponents.
Sound too easy? Well, there is another consideration. For a few JComponents that function primarily as Containers, isOpaque() is initially true and their background will be filled. JPanel is the most common example and many GUI applications make use of multiple and/or nested JPanels. The solution is to use setOpaque(false) for all lightweight containers except the one on which the desired background image is drawn. For a minor performance gain, we can go a step further, setting even that container to be transparent, and rely on the opacity of the top level container ( JApplet, JDialog, JFrame or JWindow ).
To handle both transparent and opaque states and to avoid ugly, unintended graphical effects, include the following code before drawing the image in your overridden paintComponent() method:
if( isOpaque() ) { super.paintComponent( g ); }
The line will clear and refill the background for an opaque JComponent.
The example for this article allows you to see the effects of opaque and transparent backgrounds using a tiled image.
Figure 1: JTiler Initial Display
The base JPanel ( "This" ) contains two subpanels ( "North" and
"Center" ) with contained components. The base panel shows a light pink background
when opaque, as it is on startup. The subpanels are initially set
with transparent backgrounds. Buttons at the bottom toggle the
opacity of the panels and the JLabel, so you can see the effects.
Figure 2: JTiler with Opaque North Panel
To allow the program to run without additional files, an icon
included with Swing is obtained from the UIManager. To use your
own images, comment the lines noted in the code that relate to Icon
and uncomment those for ImageIcon.
Since all operations are the same on the JComponents, the buttons are placed
in an array in the constructor and another array of matching
components is loaded. Later, when one of the buttons is pressed, in actionPerformed() the button array is searched for a match to the event source. The JComponent in the corresponding array is set
to the opposite of its current isOpaque() value and JTiler is repainted to reflect the new settings.
In paintComponent(), super.paintComponent() is conditionally called, depending
on the value returned from isOpaque(). The background image is
repeatedly drawn by starting at 0,0, and incrementing x by the image
width until the x position is at or beyond the panel width. If
vertical space is left uncovered, y is incremented by the image
height, x is set to 0, and another row is drawn. The process
continues until the panel is covered, producing the tiled effect.
|