Return-Path: <env_191067291796226841@hermes.sun.com>
Received: from pacific-carrier-annex.mit.edu by po10.mit.edu (8.9.2/4.7) id TAA24740; Tue, 23 Jul 2002 19:13:30 -0400 (EDT)
Received: from hermes.sun.com (hermes.sun.com [64.124.140.169])
	by pacific-carrier-annex.mit.edu (8.9.2/8.9.2) with SMTP id TAA07576
	for <alexp@mit.edu>; Tue, 23 Jul 2002 19:13:30 -0400 (EDT)
Date: Tue, 23 Jul 2002 12:58:58 GMT-08:00
From: "JDC Tech Tips" <body_191067291796226841@hermes.sun.com>
To: alexp@mit.edu
Message-Id: <191067291796226841@hermes.sun.com>
Subject: Core Java Technologies Tech Tips (Converting Numeric Entries, Displaying Multiline Text)
Mime-Version: 1.0
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: 7bit
X-Mailer: SunMail 1.0

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>
Technical Tips
</TITLE>
</HEAD>

<body bgcolor="#ffffff">
<a name="top"></a>
<table border="0" cellpadding="0" cellspacing="0" width="640">
<tr>
<td colspan="3" bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt=""></td>
</tr>

<tr>
<td bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt=""></td>

<td>
<table border="0" cellpadding="0" cellspacing="0" width="640">
<tr>
<td colspan="2">
<img src="http://developer.java.sun.com/images/core_java_ttips_header.gif" width="640" alt="" border="0"></td>
</tr>

<tr>
<td colspan="2" bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt=""></td>
</tr>

<!-- ================== -->
<!-- Start Main Content -->
<!-- ================== -->

<tr bgcolor="#59588d">
<td height="20">&nbsp;&nbsp;&nbsp;<a href="http://developer.java.sun.com/developer/TechTips/txtarchive/2002/July02_JohnZ.txt?s=06&w=30" style="text-decoration:none;"><font face="Verdana" size="2" color="ffffff">View this issue as simple text</font></a></td>
<td align="right" height="20"><font face="Verdana" size="2" color="ffffff"><b>July 23, 2002</b></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
</tr>
<tr>
<td colspan="2" bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt=""></td>
</tr>

<tr><td colspan="2">

<table border="0" cellpadding="10" cellspacing="0" width="640">
<tr><td>

<FORM METHOD="GET" ACTION="http://search.java.sun.com/search/java/?s=06&w=30">
<table BORDER="0" CELLPADDING="0" CELLSPACING="0" WIDTH="100%">
<tr>
<td>
        
<table BORDER="0" CELLPADDING="0" CELLSPACING="0">
<TR> 
<td  align="left" VALIGN="middle"><img src="http://developer.java.sun.com/images/issue.gif" border="0" alt=""></td>
              
<td VALIGN="middle" align="right" WIDTH="100%">
<FONT SIZE="2">
<INPUT TYPE="text" SIZE="15" MAXLENGTH="128" NAME=qt></FONT></td>
            
<td VALIGN="middle" WIDTH="55" align="right">
<INPUT TYPE="image" SRC="http://developer.java.sun.com/images/search.button.gif" ALT="Search" value="search" BORDER="0" WIDTH="55"></td>
</tr>
</table>
</td></tr>
</table>
</FORM>

<p>
<a href="#1"><img src="http://developer.java.sun.com/images/anchor.gif" border="0" alt=""><font face="Verdana" size="2" color="#666699">Converting Numeric Entries</font></a>
<br>    
<a href="#2"><img src="http://developer.java.sun.com/images/anchor.gif" border="0" alt=""><font face="Verdana" size="2" color="#666699">Displaying Multiline Text</font></a>
</p>

<p>
<font face="Verdana" size="2" color="#000000">These tips were developed using java<font size="-2"><sup>TM</sup></font> 2 SDK, Standard Edition, v 1.4.</font>
</p>

<p>
<font face="Verdana" size="2" color="#000000">This issue of the Core Java Technologies Tech Tips is written by John Zukowski.</font>
</p>

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" ALT="Pixel" border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<a name="1"></a>
<p>
<font face="Verdana" size="2" color="#000000"><b>Converting Numeric Entries</b></font>
</p>

<p>
<font face="Verdana" size="2" color="#000000">
</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
Numbers entered from the console into a computer are not entered 
as their decimal value. Internally, a number entered from the 
keyboard is represented by a Unicode value of the numerical 
representation for the locale-specific character of that number.
In other words, if an American user enters the number 1 on an 
English language system, the computer represents it as the 
Unicode value 49. The Unicode value is the the American-English, 
numerical representation of the character 1. This numerical
representation then maps to a physical representation of the 
number 1, based on the font being used. At no point is this 
character 1 thought of as the numerical value of 1.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
There are two mechanisms in the standard Java libraries that you
can use to convert a user's &quot;number&quot; input into actual numeric
values. Which mechanism you use depends on your personal 
preferences and desired feature support. For example, if you want 
to convert the user entry &quot;3.14&quot; to the value 3.14, there is a 
way to directly convert the string. Converting locale-specific 
input, such as &quot;$5,000.12&quot; to the value 5000.12, requires a 
little more work. You'll learn how to do both types of 
conversions in this tip.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
To convert from a string to a number, use the wrapper classes.
These classes offer parsing methods that do the conversion. Which 
method you use depends on the data type of the intended result:</font>
</p>

<font face="Verdana" size="2" color="#000000">
<ul>
<li>String to byte -- <code>Byte.parseByte(string)</code></li>
<li>String to short -- <code>Short.parseShort(string)</code></li>
<li>String to int -- <code>Integer.parseInt(string)</code></li>
<li>String to long -- <code>Long.parseLong(string)</code></li>
<li>String to float -- <code>Float.parseFloat(string)</code></li>
<li>String to double -- <code>Double.parseDouble(string)</code></li>
</ul>
</font>

<p><font face="Verdana" size="2" color="#000000">
The integer types (byte, short, int, and long) also offer an 
overridden version of the associated parse method. The overridden
version includes an input base as a second argument to the method. 
So, for example, if the input is in base 2, you don't have to 
manually calculate that "100" is 4.</font>
</p>

<font face="Verdana" size="2" color="#000000">
<ul>
<li>String to byte -- <code>Byte.parseByte(string, base)</code></li>
<li>String to short -- <code>Short.parseShort(string, base)</code></li>
<li>String to int -- <code>Integer.parseInt(string, base)</code></li>
<li>String to long -- <code>Long.parseLong(string, base)</code></li>
</ul>
</font>

<p><font face="Verdana" size="2" color="#000000">
The following program demonstrates these two conversion 
mechanisms. The program prompts for two numbers. When you run the 
program, and respond to the prompts, the first number you enter 
is converted to a double datatype. Be sure to try entering input 
with scientific notation, too, as in &quot;1.3E4&quot; to indicate 13000. 
The second prompt is for a hex value. Here, you can enter a hex 
value such as &quot;FFFFFF&quot; to indicate 16777215 in base 10.</font>
</p>


<font face="Verdana" size="2" color="#000000">
<pre>
import java.io.*;

public class Input {
  public static void main(String args[]) 
      throws IOException {
    InputStreamReader isr = 
      new InputStreamReader(System.in);
    BufferedReader input = new BufferedReader(isr);

    System.out.println(&quot;Enter a double: &quot;);
    String doubleString = input.readLine();
    if (doubleString != null) {
      try {
        double d = Double.parseDouble(doubleString);
        System.out.println(&quot;Double: &quot; + d);
      } catch (NumberFormatException e) {
        System.err.println(&quot;Bad input: &quot; + 
                                         doubleString);
      }
    }

    System.out.println(&quot;Enter a hex value: &quot;);
    String hexString = input.readLine();
    if (hexString != null) {
      try {
        long l = Long.parseLong(hexString, 16);
        System.out.println(&quot;Converted Hex: &quot; + l);
      } catch (NumberFormatException e) {
        System.err.println(&quot;Bad input: &quot; + hexString);
      }
    }
  }
}
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
Note: The previous example is for demonstration purposes only.
Under no circumstances should a properly created 
internationalized program accept input from the user without 
using the <code>NumberFormat</code> capabilities described below. Also, in a 
similar way, under no circumstances should a text message be 
hard-coded into a <code>println</code> statement. You should use a 
<code>ResourceBundle</code> for maintaining locale-specific messages.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
When you run the program, the interaction should look something 
like this:</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
    Enter a double: 
    1.3E4
    Double: 13000.0
    Enter a hex value: 
    FFFFFF
    Hex: 16777215
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
If the input cannot be converted, the program throws a 
<code>NumberFormatException</code> (which is indicated in this program
by &quot;Bad input:&quot;).</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
To convert formatted input, use the <code>NumberFormat</code> class of the 
<code>java.text</code> package. <code>NumberFormat</code> allows you to accept input in a 
locale-specific way, while dealing with such things as currency 
symbols, grouping separators (for example, the comma in the US or 
the period in Germany), decimal separators (for example, the 
period in the US or the comma in Germany), and percentages.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
The <code>NumberFormat</code> class is abstract. It works by using the Factory 
design pattern. You provide the details of the format you want. 
<code>NumberFormat</code> then returns an instance of a subclass that 
implements the desired input pattern. By using the returned 
instance of <code>NumberFormat</code>, you can translate the requested input 
format.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
<code>NumberFormat</code> provides a number of methods that return a specific 
format for the current default locale:</font>
</p>

<font face="Verdana" size="2" color="#000000">
<ul>
<li>Numbers -- <code>NumberFormat.getNumberInstance()</code></li>
<li>Currency -- <code>NumberFormat.getCurrencyInstance()</code></li>
<li>Percentages -- <code>NumberFormat.getPercentInstance()</code></li>
<li>Integers -- <code>NumberFormat.getIntegerInstance()</code></li>
</ul>
</font>

<p><font face="Verdana" size="2" color="#000000">
If these methods don't return the format you want, you can define 
the format yourself by creating an instance of the <code>DecimalFormat</code> 
class.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
If you want to support a locale other then the default, simply 
pass the locale as an argument to the overloaded versions:</font>
</p>

<font face="Verdana" size="2" color="#000000">
<ul>
<li>Numbers -- <code>NumberFormat.getNumberInstance(locale)</code></li>
<li>Currency -- <code>NumberFormat.getCurrencyInstance(locale)</code></li>
<li>Percentages -- <code>NumberFormat.getPercentInstance(locale)</code></li>
<li>Integers -- <code>NumberFormat.getIntegerInstance(locale)</code></li>
</ul>
</font>

<p><font face="Verdana" size="2" color="#000000">
After you get the necessary instance, you call the parse method 
to translate the string to a number.</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
  NumberFormat format = 
    NumberFormat.getNumberInstance();
  Number number = format.parse(string);
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
You can also use <code>NumberFormat</code> to format how you want to display
numbers to users. Instead of using the parse method, you use 
the format method.</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
  NumberFormat format = 
    NumberFormat.getCurrencyInstance();
  Number number = format.parse(string);
  System.out.println(format.format(number));
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
To demonstrate, the following program prompts for a double value 
and a currency amount. For the double value, you can enter an 
integer, floating point number, or use scientific notation. For
the currency amount, and for the US locale used in the example 
program, you need to start with a currency symbol (such as $). 
However, the currency amount doesn't require a grouping separator 
or decimal point. These characters are displayed in the output in 
the appropriate places.</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
import java.io.*;
import java.text.*;
import java.util.*;

public class InputFormat {
  public static void main(String args[]) 
      throws IOException {
    InputStreamReader isr = 
      new InputStreamReader(System.in);
    BufferedReader input = new BufferedReader(isr);

    System.out.println(&quot;Enter a double: &quot;);
    String doubleString = input.readLine();
    if (doubleString != null) {
      try {
        NumberFormat format = 
          NumberFormat.getNumberInstance(Locale.US);
        Number number = format.parse(doubleString);
        System.out.println(&quot;Double: &quot; + 
          number.doubleValue());
      } catch (ParseException e) {
        System.err.println(&quot;Bad input: &quot; + 
          doubleString);
      }
    }

    System.out.println(&quot;Enter a currency value: &quot;);
    String currencyString = input.readLine();
    if (currencyString != null) {
      try {
        NumberFormat format = 
          NumberFormat.getCurrencyInstance(Locale.US);
        Number number = format.parse(currencyString);
        System.out.println(&quot;Currency: &quot; + 
          format.format(number));
      } catch (ParseException e) {
        System.err.println(&quot;Bad input: &quot; + 
          currencyString);
      }
    }
  }
}
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
Although the <code>Input</code> and <code>InputFormat</code> programs function similarly, 
there are some differences. The first difference is that parsing 
with <code>NumberFormat</code> throws a <code>ParseException</code> instead of a 
<code>NumberFormatException</code>. Another, and bigger, difference has to do 
with the way parsing is done. With the different wrapper methods, 
such as <code>Integer.parseInt</code>, parsing is attempted on the entire
string. If the string as a whole is invalid, the parsing fails. 
That isn't how <code>NumberFormat.parse</code> works though. With <code>NumberFormat</code>, parsing fails (and a <code>ParseException</code> is thrown) only if there is an invalid leading character in the input.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
To demonstrate this difference, enter &quot;3.a&quot; in response to the 
prompt for a double value. The <code>Input</code> program will throw an 
exception. By comparison, the <code>InputFormat</code> program will indicate
that the input was 3.0.</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
    java Input
    Enter a double: 
    3.a
    Bad input: 3.a

    java InputFormat
    Enter a double: 
    3.a
    Double: 3.0
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
You can use <code>NumberFormat</code> to progressively parse through pieces of 
a string. There is a second version of <code>NumberFormat.parse</code> that 
accepts a second parameter indicating a parse position. You can 
use this version of the parse method to loop through a long 
string and pull out individual numbers from it. The position is 
indicated by the <code>ParsePosition</code> class, which automatically 
positions itself at the point where the parsing ends. If parsing
fails due to an invalid character, the starting and ending
position will be the same. There is no <code>ParseException</code> thrown by 
this form of the parse method.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
The following program demonstrates progressively parsing through
a string. The program prompts for set of numbers. Each number in
the set must be separated by a single non-numeric character. The
program then parses through the set, and displays the individual
numbers:</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
import java.io.*;
import java.text.*;

public class InputPieces {
  public static void main(String args[]) 
      throws IOException {
    InputStreamReader isr = 
      new InputStreamReader(System.in);
    BufferedReader input = new BufferedReader(isr);

    System.out.println(
      &quot;Enter space delimited set of numbers: &quot;);
    String bulkString = input.readLine();
    if (bulkString != null) {
      NumberFormat format = 
        NumberFormat.getNumberInstance();
      ParsePosition position = new ParsePosition(0);
      int beginIndex;
      while ((beginIndex = position.getIndex()) 
          &lt; bulkString.length()) {
        Number number = 
          format.parse(bulkString, position);
        System.out.println(
          &quot;Number: &quot; + number.doubleValue());
        int endIndex = position.getIndex();
        if (beginIndex == endIndex) {
          System.err.println(
            &quot;Parsing error, position: &quot; + endIndex);
        } else {
          position.setIndex(endIndex+1);
        }
      }
    }
  }
}
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
For input of &quot;1e54,456/3E4 8&quot; (where the separators are the e, /, 
and space) the output is:</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
    Number: 1.0
    Number: 54456.0
    Number: 30000.0
    Number: 8.0
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">    
Although the <code>getXXXInstance</code> methods of <code>NumberFormat</code> can meet most
needs for formats to accept or display, it doesn't meet every
format need. For those cases, where the <code>getXXXInstance</code> methods of 
<code>NumberFormat</code> can't meet the need, you can use the <code>DecimalFormat</code> 
class. When you call a method such as 
<code>NumberFormat.getCurrencyInstance()</code>, it creates a locale-specific 
version of <code>DecimalFormat</code> based on the type you request. Using
<code>DecimalFormat</code>, you can also create a custom <code>NumberFormat</code>.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
In general, creating a custom <code>NumberFormat</code> with <code>DecimalFormat</code> is 
done for output purposes. For example, suppose you want to 
display numbers with grouping separators (commas in the United 
States) every two positions instead of every three, and always 
with four digits after the decimal place. That would be a format 
of &quot;#,#0.0000&quot;, where each '0' indicates that a number should be 
shown at the position. Each '#' also indicates that a number
should be shown at the position, but not to show anything if the 
value is zero. The grouping separator automatically repeats to the 
left, so a display format of &quot;##,##,#0.0000&quot; is not necessary.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
Here's a program that demonstrates using the <code>DecimalFormat</code> class
to create a custom Number Format. The program prompts for a number 
and an output format. Try running the program with different 
numbers and different formatting characteristics.</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
import java.io.*;
import java.text.*;

public class InputPrompt {
  public static void main(String args[]) 
      throws IOException {
    InputStreamReader isr = 
      new InputStreamReader(System.in);
    BufferedReader input = new BufferedReader(isr);

    System.out.println(&quot;Enter number: &quot;);
    String doubleString = input.readLine();

    if (doubleString != null) {
      try {
        NumberFormat format = 
          NumberFormat.getNumberInstance();
        Number number = format.parse(doubleString);

        System.out.println(&quot;Enter format: &quot;);
        String formatString = input.readLine();

        if (formatString != null) {
          NumberFormat outputFormat = 
            new DecimalFormat(formatString);;
          System.out.println(&quot;Output: &quot; + 
            outputFormat.format(number));
        }
      } catch (ParseException e) {
        System.err.println(&quot;Bad input: &quot; + 
          doubleString);
      }
    }
  }
}
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
Here's an example of what you should see:</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
    Enter number:
    1234.56
    Enter format:
    #,#0.0000
    Output: 12,34.5600
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
For more information about using <code>NumberFormat</code>, see the
<a href="http://java.sun.com/docs/books/tutorial/i18n/format/numberFormat.html?s=06&w=30">Using Predefined Formats section of the Java Tutorial</a>.  Also, see the <a href="http://java.sun.com/docs/books/tutorial/i18n/format/decimalFormat.html?s=06&w=30">Customizing Formats section of the Java Tutorial</a> for more information on using <code>DecimalFormat</code>.</font> 
</p>

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">
<tr>
<td>
<div align="right">
<a href="#top"><font face="Verdana" size="2" color="#666699">back to top</font><img src="http://developer.java.sun.com/images/back_to_top.gif" border="0" alt=""></a>
</div>
</td></tr>

<tr><td bgcolor="#ffffff" height="2"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" ALT="Pixel" border="0"></td></tr>

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" ALT="Pixel" border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<a name="2"></a>
<p>
<font face="Verdana" size="3"><b>Displaying Multiline Text</b></font>
</p>

<p><font face="Verdana" size="2" color="#000000">
Suppose you want to create a label (either Swing <code>JLabel</code> or AWT 
<code>Label</code>) that displays multiple lines of text in a GUI. How would 
you create it? One way to do it is to create multiple labels, 
each containing one line of text, and group the labels in a 
vertical panel. Here's a program that does that:</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
import java.awt.*;
import javax.swing.*;

public class Multi1 extends JFrame {
  public Multi1() {
    super(&quot;Vertical JLabel Set&quot;);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    Container content = getContentPane();
    BoxLayout layout = 
      new BoxLayout(content, BoxLayout.Y_AXIS);
    content.setLayout(layout);
    String lines[] = {&quot;Line 1&quot;, &quot;Line 2&quot; , 
      &quot;Line 3&quot;, &quot;Line 4&quot; , &quot;Line 5&quot;};
    for (int i=0, n=lines.length; i&lt;n; i++) {
      content.add(new JLabel(lines[i]));
    }
    setSize(300, 200);
  }
  public static void main(String args[]) {
    JFrame frame = new Multi1();
    frame.show();
  }
}
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
If you run the <code>Multi1</code> program, you should see the following:<br><br>
<img src="http://developer.java.sun.com/images/tt0723_multi1.gif" alt="multi 1" border="0"></font>
</p>

<p><font face="Verdana" size="2" color="#000000">
An easier approach to displaying multiline text in a Swing label 
is to use the HTML feature of Swing text components. By prefixing 
the text label of the component with &lt;HTML&gt;, the label switches 
to HTML display mode. Then, by using HTML tags, such as &lt;BR&gt; and 
&lt;P&gt;, or by simply using regular wordwrap at the end of a line, 
you can easily display a Swing label with multiple lines of text.</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
import java.awt.*;
import javax.swing.*;

public class Multi2 extends JFrame {
  public Multi2() {
    super(&quot;HTML JLabel&quot;);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    Container content = getContentPane();
    String input = 
      &quot;&lt;HTML&gt;&lt;P ALIGN=\&quot;CENTER\&quot;&gt;&quot; +
      &quot;You're A Grand Old Flag,&lt;BR&gt;&quot; +
      &quot;You're a high fly-ing flag,&lt;BR&gt;&quot; +
      &quot;And for-ev-er, in peace, may you wave.&lt;BR&gt;&quot; +
      &quot;You're the em-blem of&lt;BR&gt;&quot; +
      &quot;the land I love,&lt;BR&gt;&quot; +
      &quot;The home of the free and the brave.&quot;;

    JLabel label = new JLabel(input);
    content.add(label, BorderLayout.CENTER);
    setSize(300, 200);
  }
  public static void main(String args[]) {
    JFrame frame = new Multi2();
    frame.show();
  }
}
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
If you run the <code>Multi2</code> program, you should see the following:<br><br>
<img src="http://developer.java.sun.com/images/tt0723_multi2.gif" alt="multi 2" border="0"></font>
</p>

<p><font face="Verdana" size="2" color="#000000">
Probably a simpler way to display multiple lines of text in a GUI
is not with a label. Instead use a text area component. A text
area component is specifically designed to support the display of
multiple lines of text. Here's a program that uses a text area 
component to display multiple lines of text:</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
import java.awt.*;
import javax.swing.*;

public class Multi3 extends JFrame {
  public Multi3() {
    super(&quot;Read-only JTextArea&quot;);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    Container content = getContentPane();
    String input = 
      &quot;I pledge allegiance to the flag of &quot; +
      &quot;the United States of America, and &quot; +
      &quot;to the republic for which it stands, &quot; +
      &quot;one nation, under God, indivisible &quot; +
      &quot;with liberty and justice for all.&quot;;

    JTextArea text = new JTextArea(input);
    text.setEditable(false);
    text.setLineWrap(true);
    text.setWrapStyleWord(true);
/*    text.setBackground(
      (Color)UIManager.get(&quot;Label.background&quot;));
    text.setForeground(
      (Color)UIManager.get(&quot;Label.foreground&quot;));
    text.setFont(
      (Font)UIManager.get(&quot;Label.font&quot;));
*/    JScrollPane pane = new JScrollPane(text);
    content.add(pane, BorderLayout.CENTER);
    setSize(300, 200);
  }
  public static void main(String args[]) {
    JFrame frame = new Multi3();
    frame.show();
  }
}
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
If you run the <code>Multi3</code> program, you should see the following:<br><br>
<img src="http://developer.java.sun.com/images/tt0723_multi3.gif" alt="multi 3" border="0"></font>
</p>

<p><font face="Verdana" size="2" color="#000000">
Notice that both line wrap and word wrap style are enabled in the 
<code>Multi3</code> program. By enabling both, you don't have to manually 
calculate what constitutes a line or worry about what font will 
be used by the HTML viewer.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
There are advantages and disadvantages to using a <code>JTextArea</code> (or 
TextArea) for the display of multiline text. One disadvantage is 
that the display of the read-only text component looks different 
than the display of the label control. This is a minor 
disadvantage, and it's something you can fix. Uncomment the six 
lines of code in the middle of the <code>Multi3</code> program to copy the 
foreground, background, and font setting over to the <code>JTextArea</code>.
Recompile. Then run the program and see the difference. The 
<code>JTextArea</code> will now look more like a <code>JLabel</code>.<br><br>
<img src="http://developer.java.sun.com/images/tt0723_multi3a.gif" alt="multi 3a" border="0"></font>
</p>

<p><font face="Verdana" size="2" color="#000000">
An advantage of using a text area component is that you do not 
have to calculate where each line breaks. Another advantage of
the text area component approach, is that you can select the 
displayed message and copy the text to the system clipboard for 
further processing. This is something that you can't easily do 
with a label.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
Swing components are usually sufficient for dealing with the
display of multiline text, but not always. For example, if you 
want to create a custom editor, you'll probably need to draw 
the multiline output yourself. In cases like this, there are 
five classes available to assist you:</font>
</p>

<ul>
<li><code>AttributedString</code></li>
<li><code>AttributedCharacterIterator</code></li>
<li><code>FontRenderContext</code></li>
<li><code>LineBreakMeasurer</code></li>
<li><code>TextLayout</code></li>
</ul>

<p><font face="Verdana" size="2" color="#000000">
These classes let you describe the text to draw, and measure how 
much text will fit on each line. Use the <code>AttributedString</code> class
to contain the text. It allows different characters of the
text string to have different attributes. However in the simplest 
case, you simply pass the quoted string to the constructor.</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
AttributedString attributedString = 
  new AttributedString(&quot;...&quot;);
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
To configure an attribute for the entire string, use the 
<code>addAttribute</code> method. For instance, to change the font for an 
entire string, specify:</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
  Font font = ...
  attributedString.addAttribute(
   TextAttribute.FONT, font);
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
To configure an attribute for just a part of the content, you 
pass in a beginning and ending index:</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
 attributedString.addAttribute(
   TextAttribute.FONT, font, startPosition, 
     endPosition);
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
The <code>TextAttribute</code> class of the <code>java.awt.font</code> package includes 
constants for the different attributes you can set. These include
foreground and background colors, font, superscript, underline, 
justification, and many others.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
You only need to configure the attributes of the string once. 
Then you need to draw the string. That's where the other classes
and interfaces help.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
When you need to draw the text, you fetch an 
<code>AttributedCharacterIterator</code> from the <code>AttributedString</code> so that the 
system can pull out the individual characters of the string.</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
  AttributedCharacterIterator characterIterator = 
    attributedString.getIterator();
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
<code>FontRenderContext</code> is used to ensure that the proper text sizes 
are used in the drawing. You obtain the <code>FontRenderContext</code> from 
the <code>Graphics2D</code> object passed into the paint method. You could 
call the constructor for <code>FontRenderContext</code>, however doing so 
wouldn't provide the correct measurements for the current graphic 
display.</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
  public void paint(Graphics g) {
    Graphics2D g2d = (Graphics2D)g;
    ...
    FontRenderContext fontRenderContext = 
      g2d.getFontRenderContext();
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
The <code>LineBreakMeasurer</code> class is used to determine how much text 
fits on a line. More specifically, given an 
<code>AttributedCharacterIterator</code> and <code>FontRenderContext</code>, 
<code>LineBreakMeasurer</code> measures how much of the <code>AttributedString</code> fits 
on each line. Each line is represented by a <code>TextLayout</code>.</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
  int screenWidth = ...;

  LineBreakMeasurer measurer = 
    new LineBreakMeasurer(characterIterator, 
      fontRenderContext);
  while (measurer.getPosition() < 
      characterIterator.getEndIndex()) {
    // Get line
    TextLayout textLayout = 
      measurer.nextLayout(screenWidth);
    ...
  }
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
That just leaves drawing the <code>TextLayout</code>, and there is a draw 
method for just that. Between lines, you just need to increase 
the y position to move down the screen.</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
  textLayout.draw(g2d, x, y);
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
Putting all the pieces together produces the following program:</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
import java.awt.*;
import javax.swing.*;
import java.awt.font.*;
import java.text.*;

public class Multi4 extends JFrame {
  String input = 
    &quot;EDWARD by the grace of God, King of &quot; +
    &quot;England, Lord of Ireland, and Duke of &quot; +
    &quot;Guyan, to all Archbishops, Bishops, etc. &quot; +
    &quot;We have seen the Great Charter of the &quot; +
    &quot;Lord HENRY, sometimes King of England, &quot; +
    &quot;our father, of the Liberties of England, &quot; +
    &quot;in these words: &quot;;
  AttributedString attributedString;

  public Multi4() {
    super(&quot;Manual Painting&quot;);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    Font font = (Font)UIManager.get(&quot;Label.font&quot;);
    attributedString = new AttributedString(input);
    attributedString.addAttribute(
      TextAttribute.FONT, font);
    Color color = 
      (Color)UIManager.get(&quot;Label.foreground&quot;);
    attributedString.addAttribute(
      TextAttribute.FOREGROUND, color);
    setSize(300, 200);
  }

  public void paint(Graphics g) {
    Graphics2D g2d = (Graphics2D)g;

    // Watch the margins
    Insets insets = getInsets();
    int width = getSize().width - 
      insets.right - insets.left;
    // Set the starting position to draw
    int x = insets.left;
    int y = insets.top;

    // Get iterator for string
    AttributedCharacterIterator characterIterator = 
      attributedString.getIterator();
    // Get font context from graphics
    FontRenderContext fontRenderContext = 
      g2d.getFontRenderContext();
    // Create measurer
    LineBreakMeasurer measurer = 
      new LineBreakMeasurer(characterIterator, 
        fontRenderContext);
    while (measurer.getPosition() &lt; 
        characterIterator.getEndIndex()) {
      // Get line
      TextLayout textLayout = 
        measurer.nextLayout(width);
      // Move down to baseline
      y += textLayout.getAscent();
      // Draw line
      textLayout.draw(g2d, x, y);
      // Move down to top of next line
      y += textLayout.getDescent() + 
        textLayout.getLeading();
    }
  }

  public static void main(String args[]) {
    JFrame frame = new Multi4();
    frame.show();
  }
}
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
If you run the <code>Multi4</code> program, you should see the following:<br><br>
<img src="http://developer.java.sun.com/images/tt0723_multi4.gif" alt="multi 4" border="0"></font>
</p>

<p><font face="Verdana" size="2" color="#000000">
For information about drawing more than text with the Java 2D API, 
see the tutorial <a href="http://java.sun.com/docs/books/tutorial/2d/display/index.html?s=06&w=30">Displaying Graphics with Graphics2D</a>.</font>
</p>

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">
<tr>
<td>
<div align="right">
<a href="#top"><font face="Verdana" size="2" color="#666699">back to top</font><img src="http://developer.java.sun.com/images/back_to_top.gif" border="0" alt=""></a>
</div>
</td></tr>

<tr><td bgcolor="#ffffff" height="2"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" ALT="Pixel" border="0"></td></tr>


<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" ALT="Pixel" border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<p>
<font face="Verdana" color="#999999" size="2">IMPORTANT: Please read our Terms of Use, Privacy, and Licensing
policies:</font><br>
<a href="http://www.sun.com/share/text/termsofuse.html?s=06&w=30"><font face="Verdana" size="2" color="#666699">http://www.sun.com/share/text/termsofuse.html</font></a><br>
<a href="http://www.sun.com/privacy/?s=06&w=30"><font face="Verdana" size="2" color="#666699">http://www.sun.com/privacy/</font></a><br>
<a href="http://developer.java.sun.com/berkeley_license.html?s=06&w=30"><font face="Verdana" size="2" color="#666699">http://developer.java.sun.com/berkeley_license.html</font></a>
</p>

<P>
<font face="Verdana" color="#999999" size="2">Comments? Send your feedback on the Java<font size="-2"><sup>TM</sup></font> Developer Technical Tips to: <a href="mailto:jdc-webmaster@sun.com"><font face="Verdana" size="2" color="#666699">jdc-webmaster@sun.com</font></a></font>
</P>

<P>
<font face="Verdana" color="#999999" size="2">Go to the <a href="http://developer.java.sun.com/subscription/?s=06&w=30"><font face="Verdana" size="2" color="#666699">subscriptions page</font></a> to subscribe or unsubscribe to this newsletter.</font>
</P>

<p>
<font face="Verdana" color="#999999" size="2">ARCHIVES: You'll find the Java Developer Connection Technical Tips archives at:</font><br>
<a href="http://developer.java.sun.com/developer/JDCTechTips/?s=06&w=30"><font face="Verdana" size="2" color="#666699">http://developer.java.sun.com/developer/JDCTechTips/</font></a>
</p>

<P>
<font face="Verdana" color="#999999" size="2">Copyright 2002 <a href="http://www.sun.com?s=06&w=30"><font face="Verdana" size="2" color="#666699">Sun Microsystems, Inc.</font></a> All rights reserved. 901 San Antonio Road, Palo Alto, California 94303 USA.</font>
</P>


<P>
<font face="Verdana" color="#999999" size="2">Sun, Sun Microsystems, Java, Java Developer Connection, and J2SE are trademarks or registered trademarks of Sun Microsystems, Inc. 
in the United States and other countries.</font>
</P>

<!-- ================ -->
<!-- End Main Content -->
<!-- ================ -->

<center>
<a href="http://www.sun.com?s=06&w=30"><img src="http://developer.java.sun.com/images/lgsun.gif" border="0" alt="Sun Microsystems, Inc."></a>
</center>

</td>
</tr>
</table>

</td></tr>
</table>
</td>

<td bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt=""></td>
</tr>
<tr>
<td colspan="3" bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt=""></td>
</tr>
</table>

<table bgcolor = "#efefef"><tr><td><a href="http://bulkmail.sun.com/servlet/PreferenceServlet?action=change&pref_name=content-type&pref_value=text&id=191067291796226841">Please send me newsletters in text.</a><br><a href="http://bulkmail.sun.com/unsubscribe?191067291796226841">Please unsubscribe me from this newsletter.</a><img src="http://bulkmail2.sun.com/OTServlet?id=191067291796226841" width=1 height=1></td></tr></table></body>
</html>		

