O'Reilly logo

Swing Hacks by Chris Adamson, Joshua Marinacci

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

26
|
Chapter 1, Basic JComponents
#6 Watermark Your Scroll Panes
HACK
H A C K
#6
Watermark Your Scroll Panes
Hack #6
This hack creates a text area with a tiled background image that is fixed,
even when the text area scrolls, and also a fixed foreground image that
appears above the text, much like the station badges now affixed to the
lower-righthand corner of most TV broadcasts.
The Swing framework was designed to let developers override portions of
every component, both the visual appearance (the view) and the behavior
(the model and controller). This design gives developers great flexibility.
One of my favorites is the
JScrollPane. Its nested composite design allows
developers to create some stunning effects.
Once again, the idea is to override the drawing code of a standard compo-
nent to create the visual effects
[Hack #5]. The difference here is that you must
deal with a composite object, the
JScrollPane. A JScrollPane is not a single
Swing component—it’s actually a wrapper around two scrollbars and the
component that does the real scrolling is a
JViewport. This viewport is the
actual target component; you will subclass it to draw both above and below
the
View component (as seen in Example 1-12). The View is the Swing wid-
get being scrolled; in this case, it is a
JTextArea.
The
ScrollPaneWatermark class inherits from JViewport, adding two meth-
ods:
setBackgroundTexture( ) and setForegroundBadge( ). Each takes a URL
instead of a File to allow for images loaded from places other than the local
disk, such as a web server or JAR file.
setBackgroundTexture( ) does the same thing that the WatermarkTextField
did in the previous hack. It loads the image, creates a same-size rectangle,
then initializes a
TexturePaint for later use. setForegroundBadge( ) is even
simpler, only loading the image and storing it in the
fgimage variable.
Example 1-12. Modifying the viewport for watermarking
public class ScrollPaneWatermark extends JViewport {
BufferedImage fgimage, bgimage;
TexturePaint texture;
public void setBackgroundTexture(URL url) throws IOException {
bgimage = ImageIO.read(url);
Rectangle rect = new Rectangle(0,0,
bgimage.getWidth(null),bgimage.getHeight(null));
texture = new TexturePaint(bgimage, rect);
}
public void setForegroundBadge(URL url) throws IOException {
fgimage = ImageIO.read(url);
}
Watermark Your Scroll Panes #6
Chapter 1, Basic JComponents
|
27
HACK
With the class set up, it’s time to draw. The code below calls super.
paintComponent( )
first, and then draws the texture on top of the component.
This is because the existing background might need to show through in case
the texture has translucent sections. This would be especially important if the
standard view background isn’t just a solid color. Under Mac OS X, for
example, the background is often a striped, light blue pattern. Here’s the
code to handle texturing:
public void paintComponent(Graphics g) {
// do the superclass behavior first
super.paintComponent(g);
// paint the texture
if(texture != null) {
Graphics2D g2 = (Graphics2D)g;
g2.setPaint(texture);
g.fillRect(0,0,getWidth(),getHeight( ));
}
}
ScrollPaneWatermark draws the foreground image badge by overriding the
paintChildren( ) method, calling the superclass, and then drawing the
image. This ensures that the badge is always on top of the children or view:
public void paintChildren(Graphics g) {
super.paintChildren(g);
if(fgimage != null) {
g.drawImage(fgimage,
getWidth( )-fgimage.getWidth(null), 0,
null);
}
}
The view (a text area in this example) will usually draw its own back-
ground. Because, by definition, the view is as big as the viewport (if not big-
ger), its background will cover up the viewport’s nice texture completely. To
stop that, you need to call
setOpaque( ) on the view:
public void setView(JComponent view) {
view.setOpaque(false);
super.setView(view);
}
The setView( ) method overrides the existing version (from JViewport) to
call
setOpaque(false) on the view before calling the super( ) method. By
putting this call here, instead of calling
setOpaque( ) from the normal setup
routines, it frees the developer using the
ScrollPaneWatermark class from
having to call
setOpaque( ) manually, making the class more reusable.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required