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

Add a Watermark to a Text Component #5
Chapter 1, Basic JComponents
|
23
HACK
H A C K
#5
Add a Watermark to a Text Component
Hack #5
This hack will show how to create a custom image background for the
JTextField, a complex Swing component that does not already support
backgrounds or icons by default.
One of Swing’s most underused features is the ability to partially override
drawing code. Most programs enhance widgets by using renderers or com-
pletely overriding the paint code. By only partially overriding the drawing,
however, you can create some very interesting effects that blend both new
and existing drawing commands.
Some components, like
JList and JTable, use renderers to customize their
look. To put a background in a
JTextField, however, requires more. The
plan is to subclass
JTextField, prepare the resources for drawing a back-
ground (loading the image, etc.), and then draw a new background while
preserving the normal
JTextField drawing code for the text and cursor.
The actual drawing will be done with a
TexturePaint. Java2D allows you to
fill any area with instances of the
Paint interface. Typically you use a color,
which is an implementation of
Paint, but it is possible to use something else,
such as a texture or gradient. This class will use a
TexturePaint to tile an
image across the component’s background.
The first step is to create a
JTextField subclass (shown in Example 1-10).
Example 1-10 creates a class called
WatermarkTextField. It is a subclass of
JTextField with a custom constructor that accepts a File object containing
an image. It also defines two member variables:
img and texture. After the
usual call to
super( ), the constructor reads the file into the BufferedImage
variable, img. If the file isn’t a valid image—or can’t be read for some other
reason—the method will throw an exception (hence the
throws IOException
clause on the constructor definition).
Example 1-10. Preparing a field for watermarking
public class WatermarkTextField extends JTextField {
BufferedImage img;
TexturePaint texture;
public WatermarkTextField(File file) throws IOException {
super( );
img = ImageIO.read(file);
Rectangle rect = new Rectangle(0,0,
img.getWidth(null),img.getHeight(null));
texture = new TexturePaint(img, rect);
setOpaque(false);
}
}
24
|
Chapter 1, Basic JComponents
#5 Add a Watermark to a Text Component
HACK
After the image is loaded successfully, the constructor creates a TexturePaint.
TexturePaints must be created with a source image and a rectangle. The
rectangle defines the portion of the source to be tiled. In this case, you want
the entire image to be used, so the rectangle is the same size as the image.
If you wanted to use just a portion of the image, you could
make the rectangle smaller. This would also give you the
ability to store all of your textures in a single large image,
which could save loading time and memory.
The last thing the WatermarkTextField constructor does before returning is
call
setOpaque(false). As you have seen earlier in this chapter (and will see
again), the
setOpaque( ) method is one of the core tools for hacking Swing.
In this case, it is used to turn off the default background of the
TextField,
allowing you to substitute your own.
With the subclass created, you can add a method to do the actual drawing:
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setPaint(texture);
g.fillRect(0,0,getWidth(),getHeight( ));
super.paintComponent(g);
}
WatermarkTextField overrides the parent class’s paintComponent( ) method with
its own version. The actual drawing is pretty simple: cast to a
Graphics2D
object (which understands how to work with Paint classes), then fill in the
background with the texture paint and call
super( ).
Earlier, I said that you will override the parent class partially rather than
completely. This is because the code still calls the parent class’s
paintComponent( ) method, but it does it after painting the new background.
Because the
opaque property is set to false, the parent class will not draw its
own background, allowing your custom one to show through. The compo-
nent will draw the text, selections, and cursors as normal on top of the cus-
tom background.
With the class ready, it’s time to pull together an example—Example 1-11.
Example 1-11. Trying out the watermarked text field
public static void main(String[] args) throws Exception {
JFrame frame = new JFrame("Watermark JTextField Hack");
JTextField textfield = new WatermarkTextField(new File("red.png"));
textfield.setText("A Text Field");

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