Chapter 17

Graphical Text


CONTENTS

Now that you know how to draw all kinds of shapes in your applets, it's time to see how to use text and text fonts, as well. By combining graphical text with other drawing methods, you can create attractive applets for your Web pages. In this chapter, you'll review how to display text, as well as how to create fonts and retrieve information about those fonts.

Dealing with Graphical Text

Earlier in this book, I said that because Windows is a device-independent graphical environment, you can't assume much about how the user's system is set up. At the time, I was talking about fonts and how different fonts take up different amounts of space in the display. After giving you this good advice, I then proceeded to ignore it. All the programs so far in this book display text strings without considering the font being used. Hopefully, you didn't run into any troubles. If you did, you'll be delighted to know that in this section, you'll learn how to solve such problems.

Getting Font Attributes

Every font that you can use with your Java applets is associated with a group of attributes that determines the size and appearance of the font. The most important of these attributes is the font's name, which determines the font's basic style. As shown in Figure 17.1, there is a big difference between the Arial and Times Roman fonts as far as how they look. When you're setting up a font for use, the name of the font is usually the first thing with which you're concerned.

Figure 17.1 : The appearance of text is determined mostly by the font you choose.

You can easily get information about the currently active font. Start by calling the Graphics object's getFont() method, like this:


Font font = g.getFont();

The getFont() method returns a Font object for the current font. Once you have the Font object, you can use the Font class's various methods to obtain information about the font. Table 17.1 shows the most commonly used public methods of the Font class and what they do.

Table 17.1  The Font Class's Most Commonly Used Public Methods.

MethodsDescription
getFamily()Returns the family name of the font.
getName()Returns the name of the font.
getSize()Returns the size of the font.
getStyle()Returns the style of the font, where 0 is plain, 1 is bold, 2 is italic, and 3 is bold italic.
isBold()Returns a boolean value indicating whether the font is bold.
isItalic()Returns a boolean value indicating whether the font is italic.
isPlain()Returns a boolean value indicating whether the font is plain.
toString()Returns a string of information about the font.

Example: Displaying Font Information

As always, the best way to see how something works is to try it out yourself. With that end in mind, Listing 17.1 is an applet that displays information about the currently active font using many of the methods described in Table 17.1. Listing 17.2 is the HTML document used to run the applet, and Figure 17.2 shows the applet running under Appletviewer.

Figure 17.2 : This is FontApplet running under Appletviewer.


Listing 17.1  FontApplet.java: Getting Information About a Font.

import java.awt.*;

import java.applet.*;



public class FontApplet extends Applet

{

    public void paint(Graphics g)

    {

        Font font = getFont();

        String name = font.getName();

        String family = font.getFamily();



        int n = font.getStyle();

        String style;

        if (n == 0)

            style = "Plain";

        else if (n == 1)

            style = "Bold";

        else if (n == 2)

            style = "Italic";

        else

            style = "Bold Italic";



        n = font.getSize();

        String size = String.valueOf(n);

        String info = font.toString();



        String s = "Name: " + name;

        g.drawString(s, 50, 50);

        s = "Family: " + family;

        g.drawString(s, 50, 65);

        s = "Style: " + style;

        g.drawString(s, 50, 80);

        s = "Size: " + size;

        g.drawString(s, 50, 95);

        g.drawString(info, 20, 125);

    }

}


Tell Java that the applet uses the classes in the awt package.
Tell Java that the applet uses the classes in the applet package.
Derive the FontApplet class from Java's Applet class.
Override the paint() method.
Get a Font object representing the active font.
Get the name of the font.
Get the family name of the font.
Get the style of the font.
Create a style string based on the value of the style integer.
Get the size of the font.
Convert the size to a string.
Get an info string for the font.
Display the font's attributes.

Listing 17.2  FONTAPPLET.htmL: The HTML Document for Running FontApplet.

<title>Applet Test Page</title>

<h1>Applet Test Page</h1>

<applet

    code="FontApplet.class"

    width=380

    height=170

    name="FontApplet">

</applet>


As you can see from Listing 17.1, using the Font class's methods is fairly straightforward. Just call the method, which returns a value that describes some aspect of the font represented by the Font object.

Getting Font Metrics

In many cases, the information you can retrieve from a Font object is enough to keep you out of trouble. For example, by using the size returned by the getSize() method, you can properly space the lines of text. Sometimes, though, you want to know more about the font you're using. For example, you might want to know the width of a particular character or even the width in pixels of an entire text string. In these cases, you need to work with text metrics.

True to form, the Java Developer's Kit includes the FontMetrics class, which makes it easy to obtain information about fonts. You create a FontMetrics object like this:


FontMetrics fontMetrics = getFontMetrics(font);

You may recall that getFontMetrics(), which returns a reference to a FontMetrics object for the active font, is a method of the Graphics class. Its single argument is the Font object for which you want the font metrics.

Once you have the FontMetrics object, you can call its methods in order to obtain detailed information about the associated font. Table 17.2 lists the most commonly used methods.

Table 17.2  Commonly Used FontMetrics Methods.

MethodDescription
charWidth()Returns the width of a character.
getAscent()Returns the font's ascent.
getDescent()Returns the font's descent.
getFont()Returns the associated Font object.
getHeight()Returns the font's height.
getLeading()Returns the font's leading (line spacing).
stringWidth()Returns the width of a string.
toString()Returns a string of information about the font.

NOTE
If you haven't used fonts before, some of the terms-leading, ascent, and descent-used in Table 17.2 may be unfamiliar to you. Leading (pronounced "ledding") is the amount of white space between lines of text. Ascent is the height of a character, from the baseline to the top of the character. Descent is the size of the area that accommodates the descending portions of letters, such as the tail on a lowercase g. Height is the sum of ascent, descent, and leading. See Figure 17.3 for examples of each.

Figure 17.3 : Ascent, descent, and leading determine the overall height of a font.

Example: Displaying Font Metrics

Most of the methods listed in Table 17.2 are self-explanatory. However, you probably want a chance to see them in action. Listing 17.3 is the source code for the MetricsApplet, and Listing 17.4 is the applet's HTML document. When you run the MetricsApplet applet, you see the window shown in Figure 17.4. At the top of the window is a text box into which you can enter different strings of text. When you press Enter, the applet displays the length of the string in pixels. Immediately below the text box is information about the current font.

Figure 17.4 : This is Appletviewer running the MetricsApplet applet.


Listing 17.3  MetricsApplet.java: An Applet That Displays Text Metrics.

import java.awt.*;

import java.applet.*;



public class MetricsApplet extends Applet

{

    TextField textField;



    public void init()

    {

        textField = new TextField(20);

        add(textField);

        textField.setText("Default string");

    }



    public void paint(Graphics g)

    {

        Font font = getFont();

        FontMetrics fontMetrics = g.getFontMetrics(font);

        int n = fontMetrics.getLeading();

        String leading = String.valueOf(n);

        n = fontMetrics.getAscent();

        String ascent = String.valueOf(n);

        n = fontMetrics.getDescent();

        String descent = String.valueOf(n);

        n = fontMetrics.getHeight();

        String height = String.valueOf(n);



        String s = textField.getText();

        n = fontMetrics.stringWidth(s);

        String width = String.valueOf(n);



        g.drawString("FONT INFO:", 55, 60);

        g.drawString("Leading: " + leading, 70, 80);

        g.drawString("Ascent: " + ascent, 70, 95);

        g.drawString("Descent: " + descent, 70, 110);

        g.drawString("Height: " + height, 70, 125);



        g.drawString("STRING INFO:", 55, 155);

        g.drawString("Width: " + width, 70, 175);

    }



    public boolean action(Event event, Object arg)

    {

        repaint();

        return true;

    }

}



Listing 17.4  METRICSAPPLET.htmL: MetricsApplet's HTML Document.

<title>Applet Test Page</title>

<h1>Applet Test Page</h1>

<applet

    code="MetricsApplet.class"

    width=200

    height=200

    name="MetricsApplet">

</applet>


NOTE
Because all of the applets you've written so far in this book haven't used text metrics when displaying text, you may wonder why you even need to bother with this stuff. Chances are that when you're running your applets under Windows 95 using the default font, everything will work fine. But remember that your applets may run on machines using other operating systems, and their default fonts may not be exactly the same size. Also, when you create your own fonts, you may not know the resultant font's size exactly. In order to position text accurately, you need to use font metrics, as you'll see later in this chapter.

Creating Fonts

You may think an applet that always uses the default font is boring to look at. In many cases, you'd be right. An easy way to spruce up an applet is to use different fonts. Luckily, Java enables you to create and set fonts for your applet. You do this by creating your own font object, like this:


Font font = new Font("TimesRoman", Font.PLAIN, 20);

The constructor for the Font class takes three arguments: the font name, style, and size. The style can be any combination of the font attributes that are defined in the Font class. Those attributes are Font.PLAIN, Font.BOLD, and Font.ITALIC.

Example: Creating a Font with Multiple Styles

Although you can create fonts with the plain, bold, or italic styles, you may at times need to combine font styles. Suppose, for example, that you wanted to use both bold and italic styles. The line


Font font = new Font("Courier", Font.BOLD + Font.ITALIC, 18);

gives you an 18-point bold italic Courier font. (A point is a measurement of a font's height and is equal to 1/72 of an inch.)

Using the Font

After you've created the font, you have to tell Java to use the font. You do this by calling the Graphics class's setFont() method, like this:


g.setFont(font);

At this point, the next text you display in your applet will use the new font. However, although you request a certain type and size of font, you can't be sure of what you'll get. The system tries its best to match the requested font, but you still need to know at least the size of the font with which you ended up. You can get all the information you need by creating a FontMetrics object, like this:


FontMetrics fontMetrics = g.getFontMetrics(font);

To get the height of a line of text, call the FontMetrics object's getHeight() method, like this:


int height = fontMetrics.getHeight();

CAUTION
When creating a font, be aware that the user's system may not have a particular font loaded. In that case, Java chooses a default font as a replacement. This possible font substitution is a good reason to use methods like Font.getName() in order to see whether you got the font you wanted. You especially need to know the size of the font, so you can be sure to position your text lines properly.

Example: Displaying Different Sized Fonts

You wouldn't create a font unless you had some text to display. The problem is that before you can display your text, you need to know at least the height of the font. Failure to consider the font's height may give you text lines that overlap or that are spaced too far apart. You can use the height returned from the FontMetrics class's getHeight() method as a row increment value for each line of text you need to print. Listing 17.5, which is the source code for the FontApplet2 applet, shows how this is done. Listing 17.6 is the applet's HTML document, and Figure 17.5 shows what the applet looks like.

Figure 17.5 : This is Appletviewer running the FontApplet2 applet.


Listing 17.5  FontApplet2.java: Displaying Different Sized Fonts.

import java.awt.*;

import java.applet.*;



public class FontApplet2 extends Applet

{

    TextField textField;



    public void init()

    {

        textField = new TextField(10);

        add(textField);

        textField.setText("32");

    }



    public void paint(Graphics g)

    {

        String s = textField.getText();

        int height = Integer.parseInt(s);



        Font font = new Font("TimesRoman", Font.PLAIN, height);

        g.setFont(font);

        FontMetrics fontMetrics = g.getFontMetrics(font);

        height = fontMetrics.getHeight();



        int row = 80;

        g.drawString("This is the first line.", 70, row);

        row += height;

        g.drawString("This is the second line.", 70, row);

        row += height;

        g.drawString("This is the third line.", 70, row);

        row += height;

        g.drawString("This is the fourth line.", 70, row);

    }



    public boolean action(Event event, Object arg)

    {

        repaint();

        return true;

    }

}



Listing 17.6  FONTAPPLET2.htmL: FontApplet2's HTML Document.

<title>Applet Test Page</title>

<h1>Applet Test Page</h1>

<applet

    code="FontApplet2.class"

    width=400

    height=200

    name="FontApplet2">

</applet>


When you run FontApplet2, you see the window shown in Figure 17.5. The size of the active font is shown in the text box at the top of the applet, and a sample of the font appears below the text box. To change the size of the font, type a new value into the text box and press Enter. Figure 17.6, for example, shows the applet displaying 12-point font, whereas Figure 17.7 is the applet displaying 120-point characters. As you can see, no matter what font size you choose, the lines are properly spaced (although large fonts overrun the boundaries of the applet's canvas).

Figure 17.6 : FontApplet2 can display any size characters you like. This is 12-point text.

Figure 17.7 : This is FontApplet2 displaying 120-point text.

The spacing of the lines is accomplished by first creating a variable to hold the vertical position for the next line of text:


int row = 80;

Here, the program not only declares the row variable, but also initializes it with the vertical position of the first row of text.

The applet then prints the first text line, using row for drawString()'s third argument:


g.drawString("This is the first line.", 70, row);

In preparation for printing the next line of text, the program adds the font's height to the row variable:


row += height;

Each line of text is printed, with row being incremented by the font's height in between, like this:


g.drawString("This is the second line.", 70, row);

row += height;

g.drawString("This is the third line.", 70, row);

Summary

In regular Windows programming, creating and using fonts is a meticulous and frustrating experience. Java, however, simplifies this task by offering the Font and FontMetrics classes. With just a few method calls, you can create the fonts you need for your applet. Displaying text with any font is as easy setting the font as the current font and getting the font's size. The font's height is especially important because a font's height determines the line spacing you must use. After you've created and set the font, any text you display will use the new font.

Review Questions

  1. What method of the Graphics class do you call to get the active font?
  2. What method of the Font class do you call to get a font's name?
  3. What method of the Font class do you call to get a font's height?
  4. Why is it important to determine the height of the current font?
  5. How do you get a reference to a FontMetrics object?
  6. When would you use a FontMetrics object to obtain information about a font instead of using the Font object?
  7. How can you determine the width of an entire text string?
  8. When referring to fonts, what is a point?
  9. Define the terms ascent, descent, baseline, and leading.
  10. How does a font's height relate to ascent, descent, and leading?
  11. How do you create and use a new font?
  12. What happens if the font you request is not available on the user's system?

Review Exercises

  1. Write an applet that displays three lines of text using the 16-point Helvetica font. Use the height returned from the Font class's getHeight() method to space your lines of text.
  2. Modify the applet you created in exercise 1 to display bold text.
  3. Modify exercise 2's applet so that it uses a FontMetric object to determine the font's height.
  4. Write an applet called FontApplet3 that provides a button that the user can click in order to switch between the Courier, TimesRoman, and Helvetica fonts. The final applet should look like Figure 17.8, displaying the text using the selected font with a height of 32 points and using the bold style. Figure 17.9 shows what the applet looks like when the user has clicked the button and switched to the TimesRoman font. (You can find the solution to this problem in the CHAP17 folder of this book's CD-ROM.

Figure 17.8 : This is FontApplet3 displaying the Courier font.

Figure 17.9 : Here's FontApplet3 displaying the TimesRoman font.