13.8 TextFields

Textfields create boxed areas to display and/or read a single line of text. See TextArea (Section 13.9) for a component that can display multiple lines. Java textfields do not permit mixed fonts or colors within a single textfield. If a textfield is being used for input, you typically allocate it (perhaps with a default entry and/or size) by specifying everything in the constructor, as follows:

      TextField lastNameField = new TextField(15);
      add(lastNameField);
      TextField langField = new TextField("Java");
      add(langField);

Textfields used only for display are similar, but require a call to setEditable to turn off input capability. Also, the value is often filled in via a separate step, since it might not be available when the textfield is first created. Here's the idea:

      TextField temperatureField = new TextField(4);
      temperatureField.setEditable(false);
      statusPanel.add(temperatureField);
      ...
      temperatureString = simulationTemperature("F");
      temperatureField.setText(temperatureString);

Constructors

public TextField()

This creates an empty textfield with a platform-dependent width (often one character).

public TextField(int numChars)

This creates an empty textfield that is the specified number of characters wide. Note that if a proportional-spaced font is being used, the definition of "the space required for N characters" is ambiguous. So the average character width is used.

public TextField(String initialString)

This creates a textfield filled with an initial string. It will be just wide enough to hold the string.

public TextField(String initialString, int numChars)

This creates a textfield of the specified width, filled with an initial string. As before, the width is based on the average width of characters in the font the textfield is using.

Example

Listing 13.25 creates a TextField with each of the four constructors. The result is shown in Figure 13-23.

Listing 13.25 TextFields.java

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

/** A TextField from each of the four constructors */

public class TextFields extends Applet {
  public void init() {
    add(new TextField());
    add(new TextField(30));
    add(new TextField("Initial String"));
    add(new TextField("Initial", 30));
  }
}

Figure 13-23 A TextField from each of the four constructors.



Other TextField Methods

A TextField is a subclass of TextComponent. The following two subsections list the methods of TextComponent and of TextField. Some of the most commonly used methods are getText and setText (for retrieving and specifying TextField contents), setEditable (for allowing or disallowing user input), getColumns and setColumns (for looking up and setting the TextField width) and setEchoChar (for specifying that "*" or some other character be displayed when text is entered, as for password fields).

TextComponent Methods

public void addTextListener(TextListener listener) [Java 1.1]
public void removeTextListener(TextListener listener) [Java 1.1]

These Java 1.1 methods let you add or remove a TextListener for processing text events. Recall that Component (Section 11.2) already supplies addKeyListener and removeKeyListener methods, but text events occur whenever the text value changes, even if the change is programmatic (i.e. via setText). A TextListener needs to implement a single method: textValueChanged. This method takes a TextEvent as an argument. To get the component's string from this event, use getSource to find the source object, cast the result to a TextComponent, and do getText on that.

public int getCaretPosition() [Java 1.1]

This lets you look up the position of the text insertion caret.

public String getSelectedText()

This returns the selected text. If no text is currently selected, a zero-length (but non-null) string is returned.

public int getSelectionEnd()

This returns the index of the first character after the end of the selected text. Zero is returned if no text is selected.

public int getSelectionStart()

This returns the index of the first character of any selected text. Zero is returned if no text is selected.

public String getText()

This returns the text in the textfield, if any. If there is no text, a zero-length (but non-null) string is returned.

public boolean isEditable()

This determines if the textfield allows user input (true) or if it is just for display (false).

public void processTextEvent(TextEvent event) [Java 1.1]

This lower-level event-processing method can be overridden to handle text events. See addTextListener for more details. You can also handle individual keyboard events, since processKeyEvent is inherited from the Component class (Section 11.2). Don't forget to enable text events, call super.processTextEvent from within the method, and import java.awt.event.*.

public void select(int startIndex, int endIndex)

This selects the text starting at startIndex, up through but not including endIndex. Selected text is highlighted on most operating systems. If the ending index is longer than the length of the text, the entire text is selected.

public void selectAll()

This selects all the text.

public void setCaretPosition(int index) [Java 1.1]

This sets the position of the text insertion caret.

public void setEditable(boolean editableStatus)

This permits (true) or prohibits (false) the user from typing into the textfield.

public void setSelectionEnd(int startIndex) [Java 1.1]

This sets the index of the first character after the end of the selected text.

public void setSelectionStart(int endIndex) [Java 1.1]

This sets the index of the first character of selected text.

public void setText(String newText)

This method replaces any text with the supplied string. An input value of null is the same as "".

TextField Methods

In addition to the TextComponent methods, the following methods are available:

public void addActionListener(ActionListener listener) [Java 1.1]
public void removeActionListener(ActionListener listener) [Java 1.1]

Action events are generated when the user hits RETURN while the textfield has the focus. These methods let you attach or remove an ActionListener to process them. In many cases, addTextListener and removeTextListener (inherited from TextComponent) or addKeyListener and removeKeyListener (inherited from Component) are of more interest.

public boolean echoCharIsSet()

This determines if an echo character been specified. See setEchoCharacter.

public int getColumns()

This method tells you the number of columns in the textfield. If you are using a proportional font, this is no guarantee that this number of characters will really fit in the textfield, however, because the value is based on the average width of characters in the current font.

public char getEchoChar()

This returns the current echo character. This value is only meaningful if echoCharIsSet is true.

public void processActionEvent(ActionEvent event) [Java 1.1]

Action events are generated when the user hits RETURN while the textfield has the focus. If you want the textfield to process its own events, you first enable AWTEvent.ACTION_EVENT_MASK, then override this method. Be sure to call super.processActionEvent in case any listeners are attached.

public void setColumns(int cols) [Java 1.1]

In Java 1.0, you cannot change the width of a textfield after it is created, aside from resizing it with resize or reshape, which is based on pixels, not characters. Java 1.1 lets you specify the width directly. Note that the width is in terms of the average width of characters in the textfield's font.

public void setEchoCharacter(char echoChar)
public void setEchoChar(char echoChar) [Java 1.1]

This specifies a character to display for each character the user types in. The actual text entered is still available from getText. The "*" character is often used for implementing fields to gather passwords or other sensitive data.

Because TextField is a subclass of Component (Section 11.2), it has access to all Component methods. Color support for textfields is relatively consistent across platforms. The only major platform not supporting colors is Netscape for MacOS, which supports neither foreground nor background colors.

Handling TextField Events

In Java 1.0, there are three event types of interest: focus events, keyboard events, and action events. Focus events happen when the textfield acquires or loses the input focus, keyboard events when the user hits a key while the textfield has the focus, and action events when the user hits RETURN while it has the focus. These events are of interest in Java 1.1 as well, plus a basic text event is generated whenever the textfield contents change due to user input or from a call to setText.

TextField Events in Java 1.0

In Java 1.0, you can monitor focus events with gotFocus and lostFocus; keyboard events with keyDown and keyUp, and action events with action. You can catch the events in the textfield itself or centralize the processing in an enclosing window. In many cases, you don't bother to catch these events at all, but simply look up the textfield contents via getText when some other event occurs (e.g., when the user clicks a button). In fact, if the textfield is being used only for display and input has been disabled via setEditable(false), no events are available.

For example, Listing 13.26 implements a spelling-corrected TextField that lets the user enter the name of a good programming language. The keyUp method is used to read the text entered so far. If the text does not match an entry in the program's database, the text is replaced by a legal substring of the same length. The gotFocus method is used to flash a subliminal hint to the user, before returning the text to the previous value. Finally, if the user hits RETURN, the text is filled in with the full name of the appropriate programming language most closely matching the text entered so far. The action method is used for this task. Figure 13-24 shows one possible result.

Listing 13.26 JavaTextField.java

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

/** Lets the user enter the name of <B>any</B>
 *  good programming language. Or does it?
 */

public class JavaTextField extends Applet {
  private TextField langField;
  private String[] substrings =
    { "", "J", "Ja", "Jav", "Java" };

  public void init() {
    setFont(new Font("TimesRoman", Font.BOLD, 14));
    setLayout(new GridLayout(2, 1));
    add(new Label("Enter a Good Programming Language",
                  Label.CENTER));
    langField = new TextField();
    Font langFont = new Font("Helvetica", Font.BOLD, 18);
    langField.setFont(langFont);
    add(langField);
  }

  /** Monitor/correct spelling as user types */
  
  public boolean keyUp(Event event, int key) {
    if (event.target == langField) {
      setLanguage();
      return(true);
    } else
      return(false);
  }

  // "Correct" the user's spelling if they've
  // made a typo.

  private void setLanguage() {
    int length = langField.getText().length();
    if (length <= 4)
      langField.setText(substrings[length]);
    else
      langField.setText("Java");
  }

  /** When they hit RETURN, fill in the right answer. */
  
  public boolean action(Event event, Object object) {
    if (event.target == langField) {
      langField.setText("Java");
      return(true);
    } else
      return(false);
  }

  /** Subliminal advertising! Give the user a hint. */
  
  public boolean gotFocus(Event event, Object ignore) {
    if (event.target == langField) {
      String text = langField.getText();
      for(int i=0; i<5; i++) {
        langField.setText("Hint: Java");
        langField.setText(text);
      }
      return(true);
    } else
      return(false);
  }
}

Figure 13-24 Textfield after "C++" entered (an obvious typo). The name will be completed when the user hits RETURN.



TextField Events in Java 1.1

In Java 1.1, there are four event types of interest: focus events, keyboard events, text events, and action events. The difference between keyboard events and text events are that text events are generated even when someone calls setText programmatically; keyboard events don't. As usual, you have the choice of handling events in the component itself using the lower-level processXxxEvent methods, or of attaching an external listener to process them. Listing 13.27 creates a Java 1.1 applet with the identical look and behavior to the JavaTextField just shown. It uses a LanguageField (Listing 13.28), which overrides processKeyEvent, processActionEvent, and processFocusEvent to implement the spelling-correction and hints. Note that the process Xxx Event of the super class is called in case a class using the LanguageField also attaches a listener to it.

Listing 13.27 JavaTextField2.java

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

/** Lets the user enter the name of <B>any</B>
 *  good programming language. Or does it?
 */

public class JavaTextField2 extends Applet {
  public void init() {
    setFont(new Font("Serif", Font.BOLD, 14));
    setLayout(new GridLayout(2, 1));
    add(new Label("Enter a Good Programming Language",
                  Label.CENTER));
    LanguageField langField = new LanguageField();
    Font langFont = new Font("SansSerif", Font.BOLD, 18);
    langField.setFont(langFont);
    add(langField);
  }
}

Listing 13.28 LanguageField.java

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

/** A spelling-correcting TextField for entering
 *  a language name.
 */

public class LanguageField extends TextField {
  private String[] substrings =
    { "", "J", "Ja", "Jav", "Java" };

  public LanguageField() {
    super();
    enableEvents(AWTEvent.KEY_EVENT_MASK |
                 AWTEvent.ACTION_EVENT_MASK |
                 AWTEvent.FOCUS_EVENT_MASK);
  }

  /** Monitor/correct spelling as user types */
  
  public void processKeyEvent(KeyEvent event) {
    if (event.getID() == event.KEY_RELEASED)
      setLanguage();
    super.processKeyEvent(event);
  }

  // "Correct" the user's spelling if they've
  // made a typo.
  
  private void setLanguage() {
    int length = getText().length();
    if (length <= 4)
      setText(substrings[length]);
    else
      setText("Java");
  }

  /** When they hit RETURN, fill in the right answer. */

  public void processActionEvent(ActionEvent event) {
    setText("Java");
    super.processActionEvent(event);
  }

  /** Subliminal advertising! Give the user a hint. */
  
  public void processFocusEvent(FocusEvent event) {
    if (event.getID() == event.FOCUS_GAINED) {
      String text = getText();
      for(int i=0; i<5; i++) {
        setText("Hint: Java");
        setText(text);
      }
    }
    super.processFocusEvent(event);
  }
}

Continue to Section 13.9 (TextAreas). Return to Chapter 13 table of contents.