Fonts and Colors

   

Fonts and colors are important attributes of JFC programs. Fonts give text an aesthetic quality and make it easier to read. Colors offer excitement and information. Without color , images would be dull and warning messages would be harder to convey . Because of their importance, Java simplifies the task of working with fonts and colors.

Getting to Know Fonts

Fonts are nothing more than sets of type. Each font has a size and face (style). Size is measured in points (units of type that are approximately 1/72 of an inch). Faces include Bold, Italic, Bold and Italic, or neither Bold nor Italic (Plain). When a program draws text, this text always appears in a specific font.

A font is given a face name that identifies its typographic design and face. For example, Courier New Bold identifies a font that has the Courier New typographic design and a Bold face.

Each font belongs to a family of fonts, and each family's fonts are related in that they share a common typographic design and a common family name. For example, Times New Roman Bold and Times New Roman Italic share the common Times New Roman family name.

Before you create a font, it's a good idea to find out what fonts are available. Prior to Java 2, you would enumerate the family names of available fonts by calling the getFontList method in the AWT's Toolkit class. (This method returns an array of String objects in which each object contains a family name.) The getFontList method was deprecated in Java 2 because a much better technique was introduced.

See "Environments, Devices, and Configurations" in Chapter 18, "Java 2D."

Under Java 1.0, getFontList returned Times Roman, Helvetica, Courier, Dialog, DialogInput, and ZapfDingbats as the family names of available fonts. For copyright and portability reasons, Java 1.1 changed Times Roman to Serif (with serifs), Helvetica to Sans Serif (without serifs), and Courier to Monospaced. (The actual fonts didn't change, just their names.) Furthermore, Zapf Dingbats was dropped from Java 1.1 because this font's characters were given official Unicode mappings in the range \ u2700 to \ u27ff. (The Java 1.1 family names are still available for use in Java 2 programs.)

The AWT's font family names are virtual family names. They are virtual because these names are mapped to the family names of physical fonts on each Java platform. As long as you use virtual family names, your font code will be portable.

Creating Fonts

You create a font by instantiating an object from the AWT's Font class (located in the java.awt package). To demonstrate font creation, the following code fragment creates a 12-point Dialog Bold Font object:

 Font f = new Font ("Dialog", Font.BOLD, 12); 

Font.BOLD is a read-only class field (declared in the Font class) that identifies a font family's Bold face. Font also declares PLAIN and ITALIC fields to identify a font family's Plain and Italic faces.

Font.BOLD and Font.ITALIC can be combined to achieve a Bold Italic face by using either the addition operator ( + ) or the bitwise OR operator ( ). This is demonstrated by the following code fragment:

 Font f = new Font ("Serif", Font.ITALIC  Font.BOLD, 36); 

After a Font object has been created, the drawing surface needs to be "told" to use this new Font. Graphics provides a setFont method to carry out this task. This method takes a Font argument and sets the drawing surface's current font to this argument. To complement setFont, Graphics also provides a getFont method that returns the drawing surface's current Font.

To see how these concepts apply, check out Listing 13.11 which presents source code to an applet called FontNamesDemo.

Listing 13.11 The FontNamesDemo Applet Source Code
 // FontNamesDemo.java import java.awt.*; import java.applet.*; public class FontNamesDemo extends Applet {    public void paint (Graphics g)    {       Font f = new Font ("Serif", Font.PLAIN, 12);       g.setFont (f);       g.drawString ("Serif - PLAIN - 12", 10, 30);       f = new Font ("Sanserif", Font.ITALIC, 10);       g.setFont (f);       g.drawString ("Sanserif - ITALIC - 10", 10, 60);       f = new Font ("Monospaced", Font.BOLD  Font.ITALIC, 14);       g.setFont (f);       g.drawString ("Monospaced - BOLD and ITALIC - 14", 10, 90);       f = new Font ("Dialog", Font.PLAIN, 12);       g.setFont (f);       g.drawString ("Dialog - PLAIN - 12", 10, 120);       f = new Font ("DialogInput", Font.BOLD + Font.ITALIC, 10);       g.setFont (f);       g.drawString ("DialogInput - BOLD and ITALIC - 10", 10, 150);    } } 

FontNamesDemo creates a Font object based on each of the virtual font family names. The setFont method is then called to establish this font as the drawing surface's current font. Finally, text is displayed using this font. Figure 13.14 shows the Applet Viewer running FontNamesDemo.

Figure 13.14. The FontNamesDemo applet shows text displayed using the AWT's virtual font family names.

graphics/13fig14.gif

Troubleshooting Tip

Sometimes, changing the font in the paint method causes the contents of a drawing surface to flicker. If this problem is bothering you, see "A Flicker-Free Drawing Surface," in the "Troubleshooting" section at the end of this chapter.


To learn more about the Font class, check out Table 13.6. This table presents commonly used Font methods .

Table 13.6. Inside the AWT's Font class
Method Description
Font (String name, int style, int size) Initializes a Font object to a specific family name, style, and size
equals (Object o) Compares the current Font object with o (which must be a Font ) for equality. A Boolean true value is returned if they are equal
getFamily () Returns a String object containing the current Font object's family name
getFontName () Returns a String object containing the current Font object's face name
getSize () Returns an int containing the current Font object's size
getStyle () Returns an int containing the current Font object's
isBold () Returns a Boolean true value if the current Font object contains the Bold style
isItalic () Returns a Boolean true value if the current Font object contains the Italic style
isPlain () Returns a Boolean true value if the current Font object uses the default Plain style
toString () Returns a String object containing a representation of the current Font object

Measuring Fonts

After you've created a font, how do you determine various font measurements, such as a character's height or the average width of characters in a proportional font? The answer is to use the FontMetrics class (located in the java.awt package).

FontMetrics, like Graphics, is an abstract class. Therefore, you cannot create objects from FontMetrics. Instead, you must call Graphics ' getFontMetrics method to return an object created from a subclass of FontMetrics. This object is associated with the graphics context's current font. The following code fragment shows how to call this method:

 public void paint (Graphics g) {    FontMetrics fm = g.getFontMetrics (); } 

Tip

You can also obtain a FontMetrics object for a specific font by calling java.awt.Toolkit 's getFontMetrics method, as demonstrated by the following code fragment:

 Font f = new Font ("Serif", Font.PLAIN, 10); FontMetrics fm; fm = Toolkit.getDefaultToolkit ().getFontMetrics (f); 

Each time you set a graphics context's current font, a new FontMetrics subclass object is automatically created. This new object replaces the previous object. Therefore, you need to call getFontMetrics after setting a new font before you can obtain measurements. This is shown in the following code fragment:

 public void paint (Graphics g) {    FontMetrics fm1 = g.getFontMetrics ();    g.setFont (new Font ("Dialog", Font.PLAIN, 12));    FontMetrics fm2 = g.getFontMetrics (); } 

Each font is associated with certain measurements. These measurements are illustrated in Figure 13.15.

Figure 13.15. Every font is associated with certain measurements.

graphics/13fig15.gif

Note

In Java, measurements are always made from a font's baseline. The portion of a character that appears below the baseline is known as a descent, whereas the portion of a character appearing above the baseline is known as an ascent. Some characters have extra visual information (such as an acute) appearing above the ascent. This extra information is known as leading (pronounced ledding). The combination of descent, ascent, and leading is known as height. Finally, the width of the current character plus any inter-character space is known as advance width.


Listing 13.12 presents source code to an applet called FontMetricsDemo. This applet demonstrates various FontMetrics methods.

Listing 13.12 The FontMetricsDemo Applet Source Code
 // FontMetricsDemo.java import java.awt.*; import java.applet.Applet; public class FontMetricsDemo extends Applet {    String the = "The ";    String [] msgs =    {       " method is handy for centering text.",       " method is handy for spacing between rows of text.",       " method returns the maximum ascent of any character.",       " method returns the maximum descent of any character."    } ;    String [] methods =    {       "stringWidth",       "getHeight",       "getMaxAscent",       "getMaxDescent"    } ;    public void paint (Graphics g)    {       // Create a Bold Serif font, establish this font       // as the graphics context font, and obtain font       // metrics for this font.       Font f1 = new Font ("Serif", Font.BOLD, 12);       g.setFont (f1);       FontMetrics fm = g.getFontMetrics ();       // Create an array to hold method name widths.       int [] wMethod = new int [methods.length];       // For each method name in the methods array,       // compute its width (in pixels) when displayed       // using the Bold font.       for (int i = 0; i < wMethod.length; i++)            wMethod [i] = fm.stringWidth (methods [i]);       // Establish a Plain Serif font as the graphics       // context font.       Font f2 = new Font ("Serif", Font.PLAIN, 12);       g.setFont (f2);       fm = g.getFontMetrics ();       // Calculate the width (in pixels) of the string       // referenced by the, when displayed using Plain       // Serif.       int wThe = fm.stringWidth (the);       // Calculate a width array for all messages.       int [] wMsg = new int [msgs.length];       // Compute each message's display width based on       // Plain Serif.       for (int i = 0; i < wMsg.length; i++)            wMsg [i] = fm.stringWidth (msgs [i]);       // For each message, determine the horizontal       // start position so that the message can be       // horizontally centered.  Then, obtain the       // current display row (taking baseline into       // account), and draw the message.  Change       // fonts (accordingly) so that method names       // appear in Bold Serif and the rest of the       // text appears in Plain Serif.       for (int i = 0; i < msgs.length; i++)       {            int x = getSize ().width - wThe - wMethod [i] - wMsg [i];            x  >>= 1; // A faster way of dividing by 2.            int y = fm.getHeight () * (i + 1);            g.drawString (the, x, y);            x += wThe;            g.setFont (f1);            g.drawString (methods [i], x, y);            x += wMethod [i];            g.setFont (f2);            fm = g.getFontMetrics ();            g.drawString (msgs [i], x, y);       }    } } 

FontMetricsDemo displays horizontally centered lines of text that are properly positioned vertically. Each line consists of one word that is displayed using the Bold style, whereas the rest of the line is displayed using the Plain style. Figure 13.16 shows FontMetricsDemo running in the Applet Viewer.

Figure 13.16. The FontMetrics Demo applet shows text centering and positioning.

graphics/13fig16.gif

Troubleshooting Tip

Right-justifying text can seem like an impossible endeavor, especially when proportional fonts are involved. If you are having trouble with this task, see "Troubleshooting" section at the end of this chapter.


To learn more about the FontMetrics class, check out Table 13.7. This table presents commonly used FontMetrics methods.

Table 13.7. Inside the AWT's FontMetrics Class
Method Description
getAscent () Returns an int containing the font ascent of the Font associated with the current FontMetrics
getDescent () Returns an int containing the font descent of the Font associated with the current FontMetrics
getHeight () Returns an int containing the standard height (leading plus ascent + descent) of the Font associated with the current FontMetrics
getLeading () Returns an int containing the leading of the Font associated with the current FontMetrics
getMaxAdvance () Returns an int containing the maximum advance width of any character in the Font associated with the current FontMetrics
getMaxAscent () Returns an int containing the maximum ascent of any character in the Font associated with the current FontMetrics
getMaxDescent () Returns an int containing the maximum descent of any character in the Font associated with the current FontMetrics
stringWidth (String s) Returns an int containing the combined advance width of all characters in s, based on the Font associated with the current FontMetrics
toString () Returns a String object containing a representation of the current FontMetrics

A Dash of Color

Colors are represented by objects created from the AWT's Color class (located in the java.awt package). Each color can be based on either the default RGB (Red, Green, Blue) color space (a mathematical model for representing colors) or a color space created from a subclass of the abstract ColorSpace class (located in the java.awt.color package).

The RGB color space requires a color to be specified by providing three primary color components (red, green, and blue) that range from 0 to 255 (0 is darkest and 255 is brightest). Furthermore, an alpha component (a measure of transparency) can be specified, but this is optional. If specified, its value ranges from 0 (completely transparent ” the background shows through) to 255 (completely opaque ” the background does not show through). (Alpha components are used with images and not with graphics drawn via Graphics 's methods ”such as drawLine. ) The following code fragment demonstrates the creation of a Color object (based on RGB) that represents the color orange.

 // Create a Color object representing orange (based on RGB). Color c = new Color (255, 200, 0); 

Three integers are passed to the constructor. The integer 255 is the red component, the integer 200 is the green component, and the integer 0 is the blue component of the resulting orange color.

For commonly used colors, the AWT predefines the following Color constants: black, blue, cyan, darkGray, gray, green, lightGray, magenta , orange, pink, red, white, and yellow. Assigning these constants to Color variables is straightforward, as illustrated by the following code fragment.

 Color c = Color.green; // Assign predefined Color green to c. 

You can extract the red, green, blue, and alpha components from a Color object by calling Color 's getRed, getGreen, getBlue, and getAlpha methods. To demonstrate, the following code fragment extracts the components from the Color.pink object.

 int red = Color.pink.getRed (); int green = Color.pink.getGreen (); int blue = Color.pink.getBlue (); int alpha = Color.pink.getAlpha (); 

After a Color object has been created, the drawing surface needs to be "told" to use this new Color. Graphics provides a setColor method to carry out this task. This method takes a Color argument and sets the drawing surface's current color to this argument. To complement setColor, Graphics also provides a getColor method that returns the drawing surface's current Color.

To see how these concepts apply, check out Listing 13.13, which presents source code to an applet called ColorDemo.

Listing 13.13 The ColorDemo Applet Source Code
 // ColorDemo.java import java.awt.*; import java.applet.Applet; public class ColorDemo extends Applet {    public void paint (Graphics g)    {       int w = getSize ().width;       int h = getSize ().height;       g.setColor (Color.red);       g.fillRect (0, 0, w  1, h  1);       g.setColor (Color.black);       g.fillOval (0, 0, w  1, h  1);       g.setColor (new Color (60, 190, 175));       FontMetrics fm = g.getFontMetrics ();       String s = "This text is aquamarine.";       int x = (w - fm.stringWidth (s)) / 2;       g.drawString (s, x, h / 2);       System.out.println ("Red = " + g.getColor ().getRed ());       System.out.println ("Green = " + g.getColor ().getGreen ());       System.out.println ("Blue = " + g.getColor ().getBlue ());       System.out.println ("Alpha = " + g.getColor ().getAlpha ());    } } 

ColorDemo uses predefined Color constants ”and a newly created Color object that represents aquamarine ”as drawing colors. The setColor method is called to establish each color as the drawing surface's current color and the getColor method is called to return the current color's Color object. This object's getRed, getGreen, getBlue, and getAlpha methods are called to extract the red, green, blue, and alpha components, which are subsequently printed. Figure 13.17 shows Applet Viewer running ColorDemo.

Figure 13.17. The ColorDemo applet shows the use of color.

graphics/13fig17.gif

HSB (hue, saturation, brightness) is another commonly used color space. Hue represents the base color, saturation represents the color's purity, and brightness represents the luminance level. The Color class provides methods for converting between RGB and HSB. If you're interested in working with HSB, consult the SDK documentation for more information on these methods.

To learn more about the Color class, check out Table 13.8. This table presents commonly used Color methods.

Table 13.8. Inside the AWT's Color Class
Method Description
Color (int rgb, boolean hasAlpha) Initializes a Color object to the red, green, and blue color components specified by rgb. Bits 16 “23 contain the red, bits 8 “15 contain the green, and bits 0 “7 contain the blue components. If hasAlpha is true, bits 24 “31 contain the alpha component. If hasAlpha is false, the alpha component defaults to 255 (completely opaque).
Color (int r, int g, int b) Initializes a Color object to a specific amount of red ( r ), green ( g ), and blue ( b ). A default value of 255 is assigned to the color's alpha component. Each color component must range from 0 to 255.
Color (int r, int g, int b, int a) Initializes a Color object to a specific amount of red ( r ), green ( g ), blue ( b ), and alpha ( a ). Each color component must range from 0 to 255.
brighter () Returns a Color object containing a brighter version of the current Color object's color.
darker () Returns a Color object containing a darker version of the current Color object's color.
equals (Object o) Compares the current Color object with o (which must be a Color ) for equality. A Boolean true value is returned if they are equal.
getAlpha () Returns an int containing the alpha component of the current Color object.
getBlue () Returns an int containing the blue component of the current Color object.
getGreen () Returns an int containing the green component of the current Color object.
getRed () Returns an int containing the red component of the current Color object.
getRGB () Returns an int containing the alpha, red, green, and blue components of the current Color object. Bits 24 “31 contain the alpha, bits 16 “23 contain the red, bits 8 “15 contain the green, and bits 0 “7 contain the blue components.
toString () Returns a String object containing a representation of the current Color object.

System Colors

You can create JFC programs that automatically adapt their colors to the current desktop color theme, used by the underlying windowing system. For example, under Windows 98, you can choose a theme in which a button's color changes from black text on a gray background to white text on a black background. These theme colors are known as system colors. By taking advantage of system colors, your JFC programs will be more user friendly.

The SystemColor class (located in the java.awt package) contains a number of constants that represent various system colors. The following code fragment shows how you would access these colors.

 public void paint (Graphics g) {    g.setColor (SystemColor.control);    g.fillRect (0, 0, getSize ().width, getSize ().height); } 

If you investigate SystemColor, you'll notice that there are two sets of constants: The first set consists of int constants that you will never need to use. They are the symbolic names of indexes into the internal system color lookup table. The second set consists of SystemColor constants. These are the constants that you will use.

This second set of constants is declared public static final. Although you cannot modify their values, the AWT can indirectly modify these values by changing the internal representation of a system color when it receives notification that the corresponding desktop color has changed. As a result, you should not compare regular Color objects with SystemColor objects by using the equals method. Instead, you call the getRGB methods in both classes to ensure that the current color values are being compared. This is demonstrated by the following code fragment.

 if (Color.red.getRGB () == SystemColor.desktop.getRGB ()) {     // whatever } 
   


Special Edition Using Java 2 Standard Edition
Special Edition Using Java 2, Standard Edition (Special Edition Using...)
ISBN: 0789724685
EAN: 2147483647
Year: 1999
Pages: 353

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