Recipe 13.5 Drawing a Drop Shadow


Problem

You want to draw text or graphical objects with a "drop shadow" effect, as in Figure 13-3.

Figure 13-3. Drop shadow text
figs/jcb2_1303.gif


Solution

Draw the component twice, with the darker shadow behind and the "real" color, slightly offset, in front.

Discussion

Program DropShadow does just this. It also uses a Font object from java.awt to exercise some control over the typeface.

The program in Example 13-1 is unabashedly an applet; to run it, you should invoke it as appletviewer DropShadow.htm (the details of such HTML files[1] are in Recipe 18.1).

[1] In all my applet examples I use a filename ending in htm instead of the more traditional html because the Javadoc program (see Recipe 23.2) overwrites the html file without notice. AppletViewer doesn't care either way.

Example 13-1. DropShadow.java
import java.applet.*; import java.awt.*; /**   * DropShadow -- show overlapped painting.  */ public class DropShadow extends Applet {     /** The label that is to appear in the window */     protected String theLabel = null;     /** The width and height */     protected int width, height;     /** The name of the font */     protected String fontName;     /** The font */     protected Font theFont;     /** The size of the font */     protected int fontSize = 18;     /** The offset for the drop shadow */     protected int theOffset = 3;     /** True if we got all required parameters */     protected boolean inittedOK = false;     /** Called from the browser to set up. We want to throw various      * kinds of exceptions but the API predefines that we don't, so we      * limit ourselves to the ubiquitous IllegalArgumentException.      */     public void init( ) {         // System.out.println("In DropShadow init( )");         theLabel = getParameter("label");         if (theLabel == null)                 throw new IllegalArgumentException("LABEL is REQUIRED");         // Now handle font stuff.         fontName = getParameter("fontname");         if (fontName == null)                 throw new IllegalArgumentException("FONTNAME is REQUIRED");         String s;         if ((s = getParameter("fontsize")) != null)             fontSize = Integer.parseInt(s);         if (fontName != null || fontSize != 0) {             theFont = new Font(fontName, Font.BOLD + Font.ITALIC, fontSize);             System.out.println("Name " + fontName + ", font " + theFont);         }         if ((s = getParameter("offset")) != null)             theOffset = Integer.parseInt(s);         setBackground(Color.green);         inittedOK = true;     }     /** Paint method showing drop shadow effect */     public void paint(Graphics g) {         if (!inittedOK)             return;         g.setFont(theFont);         g.setColor(Color.black);         g.drawString(theLabel, theOffset+30, theOffset+50);         g.setColor(Color.white);         g.drawString(theLabel, 30, 50);     }          /** Give Parameter info to the AppletViewer, just for those      * writing HTML without hardcopy documentation :-)      */     public String[][] getParameterInfo( ) {         String info[][] = {             { "label",        "string",    "Text to display" },             { "fontname",    "name",        "Font to display it in" },             { "fontsize",    "10-30?",    "Size to display it at" },         };         return info;     } }

Standard AWT uses a very simple paint model for drawing. I guess that's why the method you have to write is called paint( ). Let's go back to the paper age for a moment. If you paint something on a piece of paper and then paint over it with a different color, what happens? If you're old enough to remember paper, you'll know that the second color covers up the first color. Well, AWT works in pretty much the same way. No fair asking about water-based paints that run together; Java's painting is more like fast-drying oil paints. The fact that AWT retains all the bits (pixels, or picture elements) that you don't draw, plus the fact that methods like drawString( ) have extremely good aim, make it very easy to create a drop shadow and to combine graphics drawings in interesting ways.

Remember to draw from the back to the front, though. To see why, try interchanging the two calls to drawString( ) in the previous code.

A word of warning: don't mix drawing with added GUI components (see Chapter 14). For example, say you had a paint method in an applet or other container and had add( )ed a button to it. This works on some implementations of Java, but not on others: only the painting or the button appears, not both. It's not portable, so don't do it you've been warned! Instead, you should probably use multiple components; see the JFrame's getContentPane( ) and getGlassPane( ), discussed in Chapter 8 of Java Swing, for details.

An alternative method of obtaining a drop shadow effect is covered in Recipe 13.6.



Java Cookbook
Java Cookbook, Second Edition
ISBN: 0596007019
EAN: 2147483647
Year: 2003
Pages: 409
Authors: Ian F Darwin

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net