FontMetrics

No word wrapping is done when you draw a string in an applet, even if you embed newlines in the string with \n. If you expect that a string may not fit in the applet, you should probably use a TextArea Component instead. You'll learn about text areas and other AWT Components next class. However there are times when you will need to concern yourself with how much space a particular string will occupy. You find this out with a FontMetrics object. FontMetrics allow you to determine the height, width or other useful characteristics of a particular string, character, or array of characters in a particular font.

As an example the following program expands on the DrawString applet. Previously text would run off the side of the page if the string was too long to fit in the applet. Now the string will wrap around if necessary.

In order to tell where and whether to wrap the String, you need to measure the string, not its length in characters which can be variable but rather its width and height in pixels. Measurements of this sort on strings clearly depend on the font that's used to draw the string. All other things being equal a 14 point string will be wider than the same string in 12 or 10 point type.

To measure character and string sizes you need to look at the FontMetrics of the current font. To get a FontMetrics object for the current Graphics object you use the java.awt.Graphics.getFontMetrics() method. From java.awt.FontMetrics you'll need fm.stringWidth(String s) to return the width of a string in a particular font, and fm.getLeading() to get the appropriate line spacing for the font. There are many more methods in java.awt.FontMetrics that let you measure the heights and widths of specific characters as well as ascenders, descenders and more, but these three methods will be sufficient for this program.

Finally you'll need the StringTokenizer class from java.util to split up the String into individual words. However you do need to be careful lest some annoying beta tester (or, worse yet, end user) tries to see what happens when they feed the word antidisestablishmentarianism or supercalifragilisticexpialidocious into an applet that's 50 pixels across.

import java.applet.*;    
import java.awt.*; 
import java.util.*;
 
 
public class WrapTextApplet extends Applet {

  private String inputFromPage;

  public void init() {
    this.inputFromPage = this.getParameter("Text");
  }
  
  public void paint(Graphics g) {
  
    int line = 1;
    int linewidth = 0;
    int margin = 5;
    StringBuffer sb = new StringBuffer();
    FontMetrics fm = g.getFontMetrics();
    StringTokenizer st = new StringTokenizer(inputFromPage);
    
    while (st.hasMoreTokens()) {
      String nextword = st.nextToken();
      if (fm.stringWidth(sb.toString() + nextword) + margin < 
        this.getSize().width) {
        sb.append(nextword);
        sb.append(' ');
      }
      else if (sb.length() == 0) {
        g.drawString(nextword, margin, line*fm.getHeight());
        line++;
      }
      else {
        g.drawString(sb.toString(), margin, line*fm.getHeight());
        sb = new StringBuffer(nextword + " ");
        line++;
      }      
      
    }
    if (sb.length() > 0) {
      g.drawString(sb.toString(), margin, line*fm.getHeight());
      line++;
    }  

  }
  
}

Previous | Next | Top | Cafe au Lait

Copyright 1997, 1998, 2002 Elliotte Rusty Harold
elharo@metalab.unc.edu
Last Modified February 13, 2002