The Java 2 Standard Edition (J2SE), version 1.4, adds two new Swing components to the palette of available GUI elements: JSpinner and JFormattedTextField. We covered the JSpinner component in the very first Magic with Merlin column; we'll now explore JFormattedTextField.
While the JFormattedTextField component looks like JTextField, it acts completely different. In the simplest case, you can provide an input mask like "(###) ###-####" for a telephone number, and it will not accept any input that doesn't follow that format. In more complicated cases, there is both a display formatter and an input formatter. For example, the default date formatter permits scrolling through the available months or days based upon where the cursor is located while editing.
When working with JFormattedTextField, acceptable input is either explicitly specified by the mask or specified by a value for the component. In the latter case, the component uses the Factory design pattern to look up the default formatters for the class of the specified value. The DefaultFormatterFactory component comes with preinstalled formatters for dates, numbers, java.text.Format subclasses, and a catchall formatter for everything else.
Let's look at how to work with the component.
Masked input is typically configured by using an instance of the MaskFormatter class. Found in the javax.swing.text package, MaskFormatter works by using a series of characters to designate acceptable input. Each of the eight characters in the series represents one character in the input, as listed below:
| # | A number |
| ? | A letter |
| A | A letter or number |
| * | Anything |
| U | A letter, with lowercase characters mapped to their uppercase equivalents |
| L | A letter, with uppercase characters mapped to their lowercase equivalents |
| H | A hexadecimal digit (A-F, a-f, 0-9) |
| ' | Used to escape another mask character |
In addition to MaskFormatter, you can use the DateFormat and NumberFormat classes from the java.text package to specify the input format. Listing 1 shows some possible formats.
// Four-digit year, followed by month name and day of month,
// each separated by two dashes (--)
DateFormat format =
new SimpleDateFormat("yyyy--MMMM--dd");
DateFormatter df = new DateFormatter(format);
// US Social Security number
MaskFormatter mf1 =
new MaskFormatter("###-##-####");
// US telephone number
MaskFormatter mf2 =
new MaskFormatter("(###) ###-####");
|
Once you've specified the input format, you would then pass the formatter into the JFormattedTextField constructor, as shown below:
JFormattedTextField ftf1 = new
JFormattedTextField(df);
|
Depending on the formatter used, there are other configurable options. For instance, with MaskFormatter, you can set the placeholder character with setPlaceholderCharacter(char). Also, for date fields, it helps if you initialize the field to some value so a user will know what input format is acceptable.
That's really all there is to creating masked input fields. Listing 2 provides a complete example for you to try out the new capabilities by combining the previous code snippets. Figure 1 shows the display. Feel free to adjust the individual masks to try out the other mask characters.
Figure 1. JFormattedTextField in action

import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
import java.util.*;
import java.text.*;
public class FormattedSample {
public static void main (String args[]) throws ParseException {
JFrame f = new JFrame("JFormattedTextField Sample");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container content = f.getContentPane();
content.setLayout(new BoxLayout(content, BoxLayout.PAGE_AXIS));
// Four-digit year, followed by month name and day of month,
// each separated by two dashes (--)
DateFormat format =
new SimpleDateFormat("yyyy--MMMM--dd");
DateFormatter df = new DateFormatter(format);
JFormattedTextField ftf1 = new
JFormattedTextField(df);
ftf1.setValue(new Date());
content.add(ftf1);
// US Social Security number
MaskFormatter mf1 =
new MaskFormatter("###-##-####");
mf1.setPlaceholderCharacter('_');
JFormattedTextField ftf2 = new
JFormattedTextField(mf1);
content.add(ftf2);
// US telephone number
MaskFormatter mf2 =
new MaskFormatter("(###) ###-####");
JFormattedTextField ftf3 = new
JFormattedTextField(mf2);
content.add(ftf3);
f.setSize(300, 100);
f.show();
}
}
|
- If you missed the explanation of the
JSpinnercomponent, check out "Magic with Merlin: Swing's new Spinner component" (developerWorks, July 2001). - Learn more about
JFormattedTextField, including how to create your own input filters, from its formal documentation. - Learn about the
JFormattedTextFieldclass with its javadoc. - Learn about the
MaskFormatterclass with its javadoc. - If you aren't familiar with design patterns, you can start learning with David Gallardo's "Java design patterns 101" tutorial, exclusively from developerWorks (January 2002).
- Read the complete collection of Magic with Merlin articles by John Zukowski.
- Find other Java technology resources in the developerWorksJava technology zone.

John Zukowski conducts strategic Java consulting with JZ Ventures, Inc. and serves as the resident guru for a number of jGuru's community-driven Java FAQs. His latest books are Mastering Java 2, J2SE 1.4 and Learn Java with JBuilder 6. Reach John at jaz@zukowski.net.



