Home | | Object Oriented Programming | | The Complete Reference Java | | Internet Programming | | Web Programming | Managing Text Output Using FontMetrics - AWT Java

Chapter: Java The Complete Reference - The Java Library - Introducing the AWT: Working with Windows, Graphics, and Text

Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail

Managing Text Output Using FontMetrics - AWT Java

As just explained, Java supports a number of fonts. For most fonts, characters are not all the same dimension—most fonts are proportional.

Managing Text Output Using FontMetrics

 

As just explained, Java supports a number of fonts. For most fonts, characters are not all the same dimension—most fonts are proportional. Also, the height of each character, the length of descenders (the hanging parts of letters, such as y), and the amount of space between horizontal lines vary from font to font. Further, the point size of a font can be changed. That these (and other) attributes are variable would not be of too much consequence except that Java demands that you, the programmer, manually manage virtually all text output.

Given that the size of each font may differ and that fonts may be changed while your program is executing, there must be some way to determine the dimensions and various other attributes of the currently selected font. For example, to write one line of text after another implies that you have some way of knowing how tall the font is and how many pixels are needed between lines. To fill this need, the AWT includes the FontMetrics class, which encapsulates various information about a font. Let’s begin by defining the common terminology used when describing fonts:


Height : The top-to-bottom size of a line of text

Baseline : The line that the bottoms of characters are aligned to (not counting descent)

Ascent : The distance from the baseline to the top of a character

Descent : The distance from the baseline to the bottom of a character

Leading : The distance between the bottom of one line of text and the top of the next

 

As you know, we have used the drawString( ) method in many of the previous examples. It paints a string in the current font and color, beginning at a specified location. However, this location is at the left edge of the baseline of the characters, not at the upper-left corner as is usual with other drawing methods. It is a common error to draw a string at the same coordinate that you would draw a box. For example, if you were to draw a rectangle at coordinate 0,0, you would see a full rectangle. If you were to draw the string “Typesetting” at 0,0, you would only see the tails (or descenders) of the y, p, and g. As you will see, by using font metrics, you can determine the proper placement of each string that you display.

FontMetrics defines several methods that help you manage text output. Several commonly used ones are listed in Table 25-3. These methods help you properly display text in a window. Let’s look at some examples.

 

Displaying Multiple Lines of Text

 

Perhaps the most common use of FontMetrics is to determine the spacing between lines of text. The second most common use is to determine the length of a string that is being displayed. Here, you will see how to accomplish these tasks.

 

In general, to display multiple lines of text, your program must manually keep track of the current output position. Each time a newline is desired, the Y coordinate must be advanced to the beginning of the next line. Each time a string is displayed, the X coordinate must be set to the point at which the string ends. This allows the next string to be written so that it begins at the end of the preceding one.

 

Method : Description

 

int bytesWidth(byte b[ ], int start,  int numBytes) : Returns the width of numBytes characters held in array b, beginning at start.

 

int charWidth(char c[ ], int start,  int numChars) : Returns the width of numChars characters held in array c, beginning at start.

 

int charWidth(char c) : Returns the width of c.

 

int charWidth(int c) : Returns the width of c.

 

int getAscent( ) : Returns the ascent of the font.

 

int getDescent( ) : Returns the descent of the font.

 

Font getFont( ) : Returns the font.

 

int getHeight( ) : Returns the height of a line of text. This value can be used to output multiple lines of text in a window.

 

int getLeading( ) : Returns the space between lines of text.

 

int getMaxAdvance( ) : Returns the width of the widest character. –1 is returned if this value is not available.

 

int getMaxAscent( ) : Returns the maximum ascent.

 

int getMaxDescent( ) : Returns the maximum descent.

 

int[ ] getWidths( ) : Returns the widths of the first 256 characters.

 

int stringWidth(String str) : Returns the width of the string specified by str.

 

String toString( ) : Returns the string equivalent of the invoking object.

 

Table 25-3   A Sampling of Methods Defined by FontMetrics

 

To determine the spacing between lines, you can use the value returned by getLeading( ). To determine the total height of the font, add the value returned by getAscent( ) to the value returned by getDescent( ). You can then use these values to position each line of text you output. However, in many cases, you will not need to use these individual values. Often, all that you will need to know is the total height of a line, which is the sum of the leading space and the font’s ascent and descent values. The easiest way to obtain this value is to call getHeight( ). Simply increment the Y coordinate by this value each time you want to advance to the next line when outputting text.

 

To start output at the end of previous output on the same line, you must know the length, in pixels, of each string that you display. To obtain this value, call stringWidth( ). You can use this value to advance the X coordinate each time you display a line.

The following applet shows how to output multiple lines of text in a window. It also displays multiple sentences on the same line. Notice the variables curX and curY. They keep track of the current text output position.

 

// Demonstrate multiline output.

import java.applet.*;

 

import java.awt.*; /*

 

<applet code="MultiLine" width=300 height=100> </applet>

 

*/

public class MultiLine extends Applet { int curX=0, curY=0; // current position

 

public void init() {

 

Font f = new Font("SansSerif", Font.PLAIN, 12); setFont(f);

 

}

 

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

 

nextLine("This is on line one.", g); nextLine("This is on line two.", g); sameLine(" This is on same line.", g); sameLine(" This, too.", g); nextLine("This is on line three.", g);

 

curX = curY = 0; // Reset coordinates for each repaint.

 

}

 

// Advance to next line.

 

void nextLine(String s, Graphics g) { FontMetrics fm = g.getFontMetrics();

 

curY += fm.getHeight(); // advance to next line

curX = 0;

 

g.drawString(s, curX, curY);

 

curX = fm.stringWidth(s); // advance to end of line

 

}

 

// Display on same line.

 

void sameLine(String s, Graphics g) { FontMetrics fm = g.getFontMetrics();

 

g.drawString(s, curX, curY);

 

curX += fm.stringWidth(s); // advance to end of line

 

}

 

}

 

Sample output from this program is shown here:


Centering Text

 

Here is an example that centers text, left to right, top to bottom, in a window. It obtains the ascent, descent, and width of the string and computes the position at which it must be displayed to be centered.

 

// Center text.

import java.applet.*; import java.awt.*;

/*

 

<applet code="CenterText" width=200 height=100> </applet>

 

*/

 

public class CenterText extends Applet {

 

final Font f = new Font("SansSerif", Font.BOLD, 18);

 

public void paint(Graphics g) { Dimension d = this.getSize();

 

g.setColor(Color.white); g.fillRect(0, 0, d.width,d.height); g.setColor(Color.black); g.setFont(f);

 

drawCenteredString("This is centered.", d.width, d.height, g); g.drawRect(0, 0, d.width-1, d.height-1);

 

}

 

public void drawCenteredString(String s, int w, int h, Graphics g) {

 

FontMetrics fm = g.getFontMetrics(); int x = (w - fm.stringWidth(s)) / 2;

 

int y = (fm.getAscent() + (h - (fm.getAscent() + fm.getDescent()))/2);

 

g.drawString(s, x, y);

 

}

 

}

 

Following is a sample output from this program:



Multiline Text Alignment

 

When using a word processor, it is common for text to be aligned so that one or more of the edges of the text make a straight line. For example, most word processors can left-justify and/or right-justify text. Most can also center text. In the following program, you will see how to accomplish these actions.

In the program, the string to be justified is broken into individual words. For each word, the program keeps track of its length in the current font and automatically advances to the next line if the word will not fit on the current line. Each completed line is displayed in the window in the currently selected alignment style. Each time you click the mouse in the applet’s window, the alignment style is changed. Sample output from this program is shown here:


// Demonstrate text alignment.

import java.applet.*;

 

import java.awt.*; import java.awt.event.*; import java.util.*;

/* <title>Text Layout</title>

 

<applet code="TextLayout" width=200 height=200>

 

<param name="text" value="Output to a Java window is actually quite easy.

 

As you have seen, the AWT provides support for fonts, colors, text, and graphics. <P> Of course, you must effectively utilize these items

 

if you are to achieve professional results."> <param name="fontname" value="Serif">

 

<param name="fontSize" value="14"> </applet>

 

*/

 

public class TextLayout extends Applet { final int LEFT = 0;

 

final int RIGHT = 1; final int CENTER = 2;

final int LEFTRIGHT =3; int align;

Dimension d; Font f; FontMetrics fm; int fontSize; int fh, bl; int space; String text;

 

public void init() { setBackground(Color.white); text = getParameter("text"); try {

 

fontSize = Integer.parseInt(getParameter("fontSize"));} catch (NumberFormatException e) {

 

fontSize=14;

 

}

 

align = LEFT;

 

addMouseListener(new MyMouseAdapter(this));

 

}

 

public void paint(Graphics g) { update(g);

 

}

 

public void update(Graphics g) { d = getSize(); g.setColor(getBackground());

 

g.fillRect(0,0,d.width, d.height);

 

if(f==null) f = new Font(getParameter("fontname"), Font.PLAIN, fontSize);

 

g.setFont(f); if(fm == null) {

 

fm = g.getFontMetrics(); bl = fm.getAscent();

 

fh = bl + fm.getDescent(); space = fm.stringWidth(" ");

 

}

 

g.setColor(Color.black);

 

StringTokenizer st = new StringTokenizer(text); int x = 0;

 

int nextx; int y = 0;

 

String word, sp; int wordCount = 0; String line = "";

 

while (st.hasMoreTokens()) { word = st.nextToken(); if(word.equals("<P>")) {

 

drawString(g, line, wordCount, fm.stringWidth(line), y+bl);

 

line = ""; wordCount = 0;

x = 0;

 

y = y + (fh * 2);

 

}

 

else {

 

int w = fm.stringWidth(word);

 

if(( nextx = (x+space+w)) > d.width ) { drawString(g, line, wordCount,

 

fm.stringWidth(line), y+bl);

 

line = ""; wordCount = 0; x = 0;

 

y = y + fh;

 

}

 

if(x!=0) {sp = " ";} else {sp = "";} line = line + sp + word;

 

x = x + space + w; wordCount++;

 

}

 

}

 

drawString(g, line, wordCount, fm.stringWidth(line), y+bl);

 

}

 

public void drawString(Graphics g, String line, int wc, int lineW, int y) {

switch(align) {

 

case LEFT: g.drawString(line, 0, y); break;

 

case RIGHT: g.drawString(line, d.width-lineW,y); break;

 

case CENTER: g.drawString(line, (d.width-lineW)/2, y); break;

 

case LEFTRIGHT:

 

if(lineW < (int)(d.width*.75)) { g.drawString(line, 0, y);

 

}

 

else {

 

int toFill = (d.width - lineW)/wc;

 

int nudge = d.width - lineW - (toFill*wc); int s = fm.stringWidth(" ");

 

StringTokenizer st = new StringTokenizer(line); int x = 0;

 

while(st.hasMoreTokens()) { String word = st.nextToken(); g.drawString(word, x, y); if(nudge>0) {

 

x = x + fm.stringWidth(word) + space + toFill + 1; nudge--;

 

} else {

 

     = x + fm.stringWidth(word) + space + toFill;

 

}

 

}

 

}

}

 

}

 

}

 

class MyMouseAdapter extends MouseAdapter { TextLayout tl;

 

public MyMouseAdapter(TextLayout tl) { this.tl = tl;

 

}

 

public void mouseClicked(MouseEvent me) { tl.align = (tl.align + 1) % 4; tl.repaint();

 

}

 

}

 

Let’s take a closer look at how this applet works. The applet first creates several constants that will be used to determine the alignment style, and then declares several variables. The init( ) method obtains the text that will be displayed. It then initializes the font size in a try-catch block, which will set the font size to 14 if the fontSize parameter is missing from the HTML. The text parameter is a long string of text, with the HTML tag <P> as a paragraph separator.

 

The update( ) method is the engine for this example. It sets the font and gets the baseline and font height from a font metrics object. Next, it creates a StringTokenizer and uses it to retrieve the next token (a string separated by whitespace) from the string specified by text. If the next token is <P>, it advances the vertical spacing. Otherwise, update( ) checks to see if the length of this token in the current font will go beyond the width of the column. If the line is full of text or if there are no more tokens, the line is output by a custom version of drawString( ).

 

The first three cases in drawString( ) are simple. Each aligns the string that is passed in line to the left or right edge or to the center of the column, depending upon the alignment style. The LEFTRIGHT case aligns both the left and right sides of the string. This means that we need to calculate the remaining whitespace (the difference between the width of the string and the width of the column) and distribute that space between each of the words. The last method in this class advances the alignment style each time you click the mouse on the applet’s window.

 

Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail


Copyright © 2018-2020 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.