Easy to Learn Java: Programming Articles, Examples and Tips

Start with Java in a few days with Java Lessons or Lectures


Code Examples

Java Tools

More Java Tools!

Java Forum

All Java Tips


Submit News
Search the site here...

Swing Chapter 11. (The basics) Text Components and Undo. Easy for reading, Click here!

Custom Search
Swing Chapter 11. (The basics) Text Components and Undo. Easy for reading, Click here!

[ Return to Swing (Book) ]

Page: 1/2 

Next Page (2/2) Next Page

Chapter 11. Text Components and Undo

Subpages: 1. Text Components overview 

In this chapter:

  •          Text Components overview
  •          Undo/Redo

11.1 Text Components overview

This chapter summarizes the most basic and commonly used text component features, and introduces the undo package. In the next chapter we develop a basic JTextArea application in the process of demonstrating the use of menus and toolbars. In chapter 19 we discuss the inner workings of text components in much more detail. In chapter 20 we develop an extensive JTextPane word processor application with powerful font, style, paragraph, find & replace, and spell-checking dialogs.

11.1.1  JTextComponent

abstract class javax.swing.text.JTextComponent

The JTextComponent class serves as the super-class of each Swing text component. All text component functionality is defined by this class, along with the plethora of supporting classes and interfaces provided in the text package. The text components themselves are members of the javax.swing package: JTextField, JPasswordField, JTextArea, JEditorPane, and JTextPane.

Note: We have purposely left out most of the details behind text components in this chapter to provide only the information that you will most likely need on a regular basis. If, after reading this chapter, you would like a more thorough understanding of how text components work, and how to customize them or take advantage of some of the more advanced features, see chapters 19 and 20.

JTextComponent is an abstract sub-class of JComponent, and implements the Scrollable interface (see chapter 7). Each multi-line text component is designed to be placed in a JScrollPane

Textual content is maintained in instances of the javax.swing.text.Document interface, which acts as the text component model. The text package includes two concrete Document implementations: PlainDocument and StyledDocument. PlainDocument allows one font, one color, and is limited to character content. StyledDocument is much more complex, allowing multiple fonts, colors, embedded images and components, and various sets of hierarchically resolving textual attributes. JTextField, JPasswordField, and JTextArea each use a PlainDocument model. JEditorPane and JTextPane use a StyledDocument model. We can retrieve a text component's Document with getDocument(), and assign one with setDocument(). We can also attach DocumentListeners to a document to listen for changes in that document's textual content (this is much different than a key listener because all document events are dispatched after a change has been made).

We can assign and retrieve the color of a text component's Caret with setCaretColor() and getCaretColor(). We can also assign and retrieve the current Caret position in a text component with setCaretPosition() and getCaretPosition().

The disabledColor property allows assignment of a font color to use when in the disabled state. The foreground and background properties inherited from JComponent also apply, where the foreground color is used as the font color when a text component is enabled, and the background color is used as the background for the whole text component. The font property specifies the font to render the text in. Note that the font property, and the foreground and background color properties, do not overpower any attributes assigned to styled text components such as JEditorPane and JTextPane.

All text components maintain information about their current selection. We can retrieve the currently selected text as a String with getSelectedText(), and we can assign and retrieve specific background and foreground colors to use for selected text with setSelectionBackground()/getSelectionBackground() and setSelectionForeground()/getSelectionForeground() respectively.

JTextComponent also maintains a bound focusAccelerator property, which is a char that is used to transfer focus to a text component when the corresponding key is pressed simultaneously with the ALT key. This works internally by calling requestFocus() on the text component, and will occur as long as the top-level window containing the given text component is currently active. We can assign/retrieve this character with setFocusAccelerator()/getFocusAccelerator(), and we can turn this functionality off by assigning '\0'.

The read() and write() methods provide convenient ways to read and write text documents respectively. The read() method takes a java.io.Reader and an Object describing the Reader stream, and creates a new document model appropriate to the given text component containing the obtained character data. The write() method stores the content of the document model into a given java.io.Writer stream.

Warning: We can customize any text component's document model. However, it is important to realize that whenever the read() method is invoked a new document will be created. Unless this method is overriden, a custom document that had been assigned with setDocument() will be lost whenever read() is invoked, because the current document will be replaced by a default instance.

11.1.2  JTextField

class javax.swing.JTextField

JTextField is a single-line text component using a PlainDocument model. The horizonatlAlignment property specifies text justification within the text field. We can assign/retrive this property with setHorizontalAlignment()/getHorizontalAlignment, and acceptable values are JTextField.LEFT, JTextField.CENTER, and JTextField.RIGHT.

There are several JTextField constructors, two of which allow us to specify a number of columns. We can also assign/retrieve this number, the columns property, with setColumns()/getColumns(). Specifying a specific number of columns rarely corresponds to the actual number of characters that will fit in that text field. Firstly because a text field might not receive its preferred size due to the current layout manager. Second, the width of a column is the width of the character 'm' in the current font. Unless a monospaced font is being used, this width will be greater than most other characters.

The following example creates 14 JTextFields with a varying number of columns. Each field contains a number of 'm's equal to its number of columns.

The Code: JTextFieldTest.java

see \Chapter11\1

import javax.swing.*;

import java.awt.*;

public class JTextFieldTest extends JFrame


  public JTextFieldTest() {

    super("JTextField Test");

    getContentPane().setLayout(new FlowLayout());

    JTextField textField1 = new JTextField("m",1);

    JTextField textField2 = new JTextField("mm",2);

    JTextField textField3 = new JTextField("mmm",3);

    JTextField textField4 = new JTextField("mmmm",4);

    JTextField textField5 = new JTextField("mmmmm",5);

    JTextField textField6 = new JTextField("mmmmmm",6);

    JTextField textField7 = new JTextField("mmmmmmm",7);

    JTextField textField8 = new JTextField("mmmmmmmm",8);

    JTextField textField9 = new JTextField("mmmmmmmmm",9);

    JTextField textField10 = new JTextField("mmmmmmmmmm",10);

    JTextField textField11 = new JTextField("mmmmmmmmmmm",11);

    JTextField textField12 = new JTextField("mmmmmmmmmmmm",12);

    JTextField textField13 = new JTextField("mmmmmmmmmmmmm",13);

    JTextField textField14 = new JTextField("mmmmmmmmmmmmmm",14);


















  public static void main(String argv[]) {

    new JTextFieldTest();



Figure 11.1 illustrates. Note that none of the text completely fits in its field. This is because JTextField does not factor in the size of its border when calculating its preferred size, as we might expect. To work around this problem, although not an ideal solution, we can add one more column to each text field. The result is shown in figure 11.2. This solution is more appropriate when a fixed width font (monospaced) is being used. Figure 11.3 illustrates.

Figure 11.1 JTextFields using an equal number of columns and 'm' characters.

Figure 11.2 JTextFields using one more column than number of 'm' characters.

Figure 11.3 JTextFields using a monospaced font, and one more column than number of 'm characters.

Note: Using a monospaced font is always more appropriate when a fixed character limit is desired.

JTextField also maintains a BoundedRangeModel (see chapter 13) as its horizontalVisibility property. This model is used to keep track of the amount of currently visible text. The minimum is zero (the beginning of the document), and the maximum is equal to the width of the text field or the total length of the text in pixels (whichever is greater). The value is the current offset of the text displayed at the left edge of the field, and the extent is the width of the text field in pixels.

By default a KeyStroke (see 2.13.2) is established with ENTER that causes an ActionEvent to be fired. By simply adding an ActionListener to a JTextField we will receive events whenever ENTER is pressed while that field has the current focus. This is very convenient functionality, but it may also get in the way of things. To remove this registered keystroke we can do the following:

  KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);

  Keymap map = myJTextField.getKeymap();


JTextField's document model can be customized to allow only certain forms of input by extending PlainDocument and overriding the insertString() method. The following code shows a class that will only allow six or less digits to be entered. We can assign this document to a JTextField with the setDocument() method (see chapter 19 for more about working with Documents).

    class SixDigitDocument extends PlainDocument


      public void insertString(int offset,

       String str, AttributeSet a)

        throws BadLocationException {

          char[] insertChars = str.toCharArray();       

          boolean valid = true;

          boolean fit = true;

          if (insertChars.length + getLength() <= 6)   {

            for (int i = 0; i < insertChars.length; i++) {

              if (!Character.isDigit(insertChars[i])) {

                valid = false;






            fit = false;

          if (fit && valid)

            super.insertString(offset, str, a);

          else if (!fit)




UI Guideline : Don't overly restrict input

Filtering text fields during data entry is a powerful aid to usability. It helps prevent the user from making a mistake and can speed operation by removing the need for validation and correction procedures. However, it is important not to overly restrict the allowable input. Ensure that all reasonable input is expected and accepted.

For example, with a phone number, allow "00 1 44 654 7777" and allow "00+1 44 654 7777" and allow "00-1-1-654-7777" as well as "00144654777". Phone numbers can contain more than just numbers!
Another example might be dates. You should allow "04-06-99", "04/06/99" and "04:06:99" as well as "040699".

11.1.3  JPasswordField

class javax.swing.JPasswordField

JPasswordField is a fairly simple extension of JTextField that displays an echo character instead of the actual content that is placed in its model. This echo character defaults to '*', and we can assign a different one with setEchoChar().

Unlike other text components, we cannot retrieve the actual content of a JPasswordField with getText() (this method, along with setText() have been deprecated in JPasswordField). Instead we must use the getPassword() method, which returns an array of chars. Also note that JPasswordField overrides the JTextComponent copy() and cut() methods to do nothing but emit a beep (for security reasons).

Figure 11.4 shows the JTextFieldDemo example of section 11.1.2, using JPasswordFields instead, each using a monospaced font.

Figure 11.4 JPasswordFields using a monospaced font, and one more column than number of characters.

11.1.4  JTextArea

class javax.swing.JTextArea

JTextArea allows multiple lines of text and, like JTextField, it uses a PlainDocument model. As we discussed above, JTextArea cannot display multiple fonts or font colors. JTextArea can perform line wrapping, and when line wrapping is enabled, we can specify whether lines break on word boundaries or not. To enable/disable line wrapping we set the lineWrap property with setLineWrap(). To enable/disable wrapping on boundaries (which will only have an effect when lineWrap is set to true) we set the wrapStyleWord property using setWrapStyleWord(). Note that both lineWrap and wrapStyleWord are bound properties.

JTextArea overrides isManagingFocus() (see 2.12) to return true, indicating that the FocusManager will not transfer focus out of a JTextArea when TAB is pressed. Instead a TAB is inserted into the document, which is a number of spaces equal to tabSize. We can assign/retrieve the tab size with setTabSize()/getTabSize() respectively. tabSize is also a bound property.

There are several ways to add text to a JTextArea's document. We can pass this text in to one of the constructors, append it to the end of the document using the append() method, insert a string at a given character offset using the insert() method, or replace a given range of text with the replaceRange() method. As with any text component, we can also set the text with the JTextComponent setText() method, and we can add and remove text directly from its Document (see chapter 19 for more details about the Document interface).

JTextArea maintains lineCount and rows properties which can easily be confused. The rows property specifies how many rows of text JTextArea is actually displaying. This may change whenever a text area is resized. The lineCount property specifies how many lines of text the document contains. This usually means a set of characters ending with a line break ('\n'). We can retrieve the character offset of the end of a given line with getLineEndOffset(), the character offset of the beginning of a given line with getLineStartOffset(), and the line number that contains a given offset with getLineOfOffset().

The rowHeight and columnWidth properties are determined by the height and with of  the current font respectively. The width of one column is equal to the width of the 'm' character in the current font. We cannot assign new values to the properties, but we can override the getColumnWidth() and getRowHeight() methods in a sub-class to return any value we like. We can explicitly set the number of rows and columns a text area contains with setRows() and setColumns(), and the getRows() and getColumns() methods will only return these explicitly assigned values (not the current row and column count as we might assume at first glance).

Unless placed in a JScrollPane or a container using a layout manager which enforces a certain size (or a layout manager using the preferredSize of its children), JTextArea will resize itself dynamically depending on the amount of text entered. This behavior is rarely desired.

11.1.5  JEditorPane

class javax.swing.JEditorPane

JEditorPane is a multi-line text component capable of displaying and editing various different types of content. Swing provides support for HTML and RTF, but there is nothing stopping us from defining our own, or implementing support for an alternate format.

Note: Swing's support for HTML and RTF is located in the javax.swing.text.html and javax.swing.text.rtf packages respectively. At the time of this writing the html package was still going through major changes. The rtf package was also still under development, but was closer to a finalized state than HTML support. For this reason we devoted chapter 20 to the step-wise construction of an RTF word processor application. We expect to see stronger support for displaying and editing HTML in a future Java 2 release.

Support for different content is accomplished in part through the use of custom EditorKit objects. JEditorPane's contentType property is a String representing the type of document the editor pane is currently set up to display. The EditorKit maintains this value which, for DefaultEditorKit, defaults to "text/plain." HTMLEditorKit and RTFEditorKit have contentType values of "text/html" and "text/rtf" respectively (see chapter 19 for more about EditorKits).

In chapter 9 we built a simple web browser using a non-editable JEditorPane by passing a URL to its constructor. When in non-editable mode JEditorPane displays HTML pretty much as we might expect (although it has a long way to go to match Netscape). By allowing editing, JEditorPane will display an HTML document with many of its tags specially rendered as shown in figure 11.1 (compare this to figure 9.4).

Figure 11.5 JEditorPane displaying HTML in editable mode.

JEditorPane is smart enough to use an appropriate EditorKit, if one is available, to display a document passed to it. When displaying an HTML document, JEditorPane fires HyperlinkEvents (defined in the javax.swing.event package). We can attach HyperlinkListeners to JEditorPane to listen for hyperlink invocations, as demonstrated by the examples at the end of chapter 9. The following code shows how simple it is to construct an HTML browser using an active HyperlinkListener.

  m_browser = new JEditorPane(

    new URL("http://java.sun.com/products/jfc/tsc/index.html"));


  m_browser.addHyperlinkListener( new HyperlinkListener() {

    public void hyperlinkUpdate(HyperlinkEvent e) {

      if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {

        URL url = e.getURL();

        if (url == null)


        try { m_browser.setPage(e.getURL); }

        catch (IOException e) { e.printStackTrace(); }




JEditorPane uses a Hashtable to store its editor kit/content type pairs. We can query this table and retrieve the editor kit associated with a particular content type, if there is one, using the getEditorKitForContentType() method. We can get the current editor kit with getEditorKit(), and the current content type with getContentType(). We can set the current content type with setContentType(), and if there is an appropriate editor kit in JEditorPane's hash table the appropriate editor kit will replace the current one. We can also assign an editor kit for a given content type using the setEditorKitForContentType() method (we will discuss EditorKits, and the ability to construct our own, in chapter 19).

JEditorPane uses a DefaultStyledDocument as its model. In HTML mode an HTMLDocument, which extends DefaultStyledDocument, is used. DefaultStyledDocument is quite powerful, allowing us to associate attributes with characters, paragraphs, and apply logical styles (see chapter 19).

11.1.6  JTextPane

class javax.swing.JTextPane

JTextPane extends JEditorPane and thus inherits its abilities to display various types of content. The most significant functionality JTextPane offers is the ability to programmatically assign attributes to regions of its content, and embed components and images within its document.

To assign attributes to a region of document content we use an AttributeSet implementation. We will describe AttributeSets in detail in chapter 19, but it suffices to say here that they contain a group of attributes such as font type, font style, font color, paragraph and character properties, etc. These attributes are assigned through the use of various static methods defined in the StyleConstants class, which we will also discuss further in chapter 19.

The following example demonstrates embedded icons, components, and stylized text. Figure 11.6 illustrates.

Figure 11.6 JTextPane with inserted ImageIcons, text with attributes, and an active JButton.

The Code: JTextPaneDemo.java

see \Chapter11\2

import java.awt.*;

import java.awt.event.*;

import java.io.*;

import javax.swing.*;

import javax.swing.text.*;

public class JTextPaneDemo extends JFrame


  static SimpleAttributeSet ITALIC_GRAY = new SimpleAttributeSet();

  static SimpleAttributeSet BOLD_BLACK = new SimpleAttributeSet();

  static SimpleAttributeSet BLACK = new SimpleAttributeSet();

  JTextPane m_editor = new JTextPane();

  // Best to reuse attribute sets as much as possible.

  static {

    StyleConstants.setForeground(ITALIC_GRAY, Color.gray);

    StyleConstants.setItalic(ITALIC_GRAY, true);

    StyleConstants.setFontFamily(ITALIC_GRAY, "Helvetica");

    StyleConstants.setFontSize(ITALIC_GRAY, 14);

    StyleConstants.setForeground(BOLD_BLACK, Color.black);

    StyleConstants.setBold(BOLD_BLACK, true);

    StyleConstants.setFontFamily(BOLD_BLACK, "Helvetica");

    StyleConstants.setFontSize(BOLD_BLACK, 14);    

    StyleConstants.setForeground(BLACK, Color.black);

    StyleConstants.setFontFamily(BLACK, "Helvetica");

    StyleConstants.setFontSize(BLACK, 14);


  public JTextPaneDemo() {

    super("JTextPane Demo");

    JScrollPane scrollPane = new JScrollPane(m_editor);

    getContentPane().add(scrollPane, BorderLayout.CENTER);


    m_editor.insertIcon(new ImageIcon("manning.gif"));

    insertText("\nHistory: Distant\n\n", BOLD_BLACK);


    m_editor.insertIcon(new ImageIcon("Lee_fade.jpg"));

    insertText("                                    ", BLACK);


    m_editor.insertIcon(new ImageIcon("Bace_fade.jpg"));

    insertText("\n      Lee Fitzpatrick            "

      + "                                    "

      + "Marjan Bace\n\n", ITALIC_GRAY);

    insertText("When we started doing business under " +

      "the Manning name, about 10 years ago, we were a very " +

      "different company. What we are now is the end result of " +

      "an evolutionary process in which accidental " +

      "events played as big a role, or bigger, as planning and " +

      "foresight.\n", BLACK);


    JButton manningButton = new JButton("Visit Manning");

    manningButton.addActionListener(new ActionListener() {

      public void actionPerformed(ActionEvent e) {


        try { m_editor.setPage("http://www.manning.com"); }

        catch (IOException ioe) { ioe.printStackTrace(); }







  protected void insertText(String text, AttributeSet set) {

    try {


        m_editor.getDocument().getLength(), text, set);


    catch (BadLocationException e) {




  protected void setEndSelection() {




  public static void main(String argv[]) {

    new JTextPaneDemo();



As demonstrated above, we can insert images and components with JTextPane's insertIcon() and insertComponent() methods. Note that these methods insert the given object by replacing the current selection. If there is no current selection they will be placed at the beginning of the document. This is why we defined the setEndSelection() method in our example above to point the selection to the end of the document where we want to do insertions.

When inserting text, we cannot simply append it to the textpane itself. Instead we retrieve its document and call insertString(). To give attributes to inserted text we can construct AttributeSet implementations, and assign attributes to that set using the StyleConstants class. In the example above we do this by constructing three SimpleAttributeSets as static instances (so that they may be reused as much as possible).

As an extension of JEditorPane, JTextPane uses a DefaultStyledDocument for its model. Text panes use a special editor kit, DefaultStyledEditorKit, to manage their Actions and Views. JTextPane also supports the use of Styles, which are named collections of attributes. We will discuss styles as well as many other advanced features of JTextPane in chapters 19 and 20.

[ Return to Swing (Book) ]

Top 10 read Java Articles
 Get free "1000 Java Tips eBook"

 Java Calendar and Date: good to know facts and code examples

 Array vs ArrayList vs LinkedList vs Vector: an excellent overview and examples

 How can I convert any Java Object into byte array? And byte array to file object

 The Java Lesson 1: What is Java?

 How do I compare two dates and times, date between dates, time between times and

 Maven vs Ant or Ant vs Maven?

 How to open, read, write, close file(s) in Java? Examples on move, rename and de

 Java Array

 Java: JLabel font and color

[ More in News Section ]
Java Lessons

The Java Lesson 1:
What is Java?
The Java Lesson 2:
Anatomy of a simple Java program
The Java Lesson 3:
Identifiers and primitive data types
The Java Lesson 4:
Variables, constants, and literals
The Java Lesson 5:
Arithmetic operations, conversions, and casts
The Java Lesson 6:
Boolean expressions and operations
The Java Lesson 7:
Bitwise operations
The Java Lesson 8:
Flow control with if and else
The Java Lesson 9:
switch statements
The Java Lesson 10:
for, while, and do-while statements
The Java Lesson 11:
Using break and continue
The Java Lesson 12:
Class methods and how they are called
The Java Lesson 13:
Using the Math class
The Java Lesson 14:
Creating and calling custom class methods
The Java Lesson 15:
Overloading class methods
The Java Lesson 16:
An introduction to objects and object references
The Java Lesson 17:
The String class
The Java Lesson 18:
The StringBuffer class
The Java Lesson 19:
Initializing and processing arrays of primitives
The Java Lesson 20:
Initializing and processing arrays of objects
The Java Lesson 23:
Inheritance and overriding inherited methods
The Java Lesson 24:
abstract classes and polymorphism
The Java Lesson 25:
Interfaces, instanceof, and object conversion and casting
The Java Lesson 26:
Introduction to graphical programming and the java.awt packa
The Java Lesson 27:
The Component class
The Java Lesson 28:
Containers and simple layout managers
The Java Lesson 29:
The Color and Font classes
The Java Lesson 30:
Drawing geometric shapes
The Java Lesson 31:
Choice, List, and Checkbox controls
The Java Lesson 32:
Using the Scrollbar graphical control
The Java Lesson 33:
Menus and submenus
The Java Lesson 34:
An introduction to applets and the Applet class
The Java Lesson 35:
Essential HTML to launch an applet and pass it parameters
The Java Lesson 36:
Mouse event processing
Java Lesson 37:
Menus and submenus
Java Lesson 38:
The WindowListener interface and the WindowAdapter class
Java Lesson 39:
An introduction to GridBagLayout
Java Lesson 40:
An introduction to the Java Collections API
Java Lesson 41:
Exception handling with try, catch, and finally blocks
Java Lesson 42:
Claiming and throwing exceptions
Java Lesson 43:
Multithreading, the Thread class, and the Runnable interface
Java Lesson 44:
An introduction to I/O and the File and FileDialog classes
Java Lesson 45:
Low-level and high-level stream classes
Java Lesson 46:
Using the RandomAccessFile class
Java Lessons by
Joh Huhtala: Update

Latest articles
 Java Profiler JProbe to Resolve Performance Problems Faster

 SSL with GlassFish v2, page 5

 SSL with GlassFish v2, page 4

 SSL with GlassFish v2, page 3

 SSL with GlassFish v2, page 2

 The Java Lesson 2: Anatomy of a simple Java program, page 2

 New site about Java for robots and robotics: both software and hardware.

 Exceptions -III: What's an exception and why do I care?

 Exceptions -II: What's an exception and why do I care?

 Exceptions: What's an exception and why do I care?

 Double your Java code quality in 10 minutes, here is receipt

 Murach's Java Servlets and JSP

 How to get ascii code from a char in Java?

 Can we just try without catch? Yes!

 Make Tomcat page load faster

 Make your Tomcat More secure - limit network address for certain IP addresses

 New Java book online starts now here...

 Implementing RESTful Web Services in Java

 Firefox trimming from 1 GB to 40 Mb with many tabs opened

 SSL with GlassFish v2

 My request to replublish Tech Tips

 Search JavaFAQ.nu site here

 New Advanced Installer for Java 6.0 brings XML updates and imports 3rd party MSI

 EJB programming restrictions

 Maven vs Ant or Ant vs Maven?

 Why Java does not use default value which it should?

 How to unsign signed bytes in Java - your guide is here

 The Java Lesson 3: Identifiers and primitive data types. Page 2

 The Java Lesson 7: Bitwise operations with good examples, click here! Page 4

 The Java Lesson 7: Bitwise operations with good examples, click here! Page 3

[ More in News Section ]

Home Code Examples Java Forum All Java Tips Books Submit News, Code... Search... Offshore Software Tech Doodling

RSS feed Java FAQ RSS feed Java FAQ News     

    RSS feed Java Forums RSS feed Java Forums

All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest 1999-2006 by Java FAQs Daily Tips.

Interactive software released under GNU GPL, Code Credits, Privacy Policy