MIDP GUI Programming, Part 2

This is the second in a series of articles from O'Reilly's Learning Wireless Java, by Qusay Mahmoud. This section from Chapter 5 focuses on the high-level MIDP GUI APIs and components. You can also read the first excerpt in this series.

The High-Level MIDP APIs

Let's look at how the various classes in the high-level API can be used to create GUI components. We will cover two parts of this process: working with screens and the components that subclass them, and working with forms and the components that can be arranged in them.

Working with Screens

Having seen an example of a screen, a few questions immediately come to mind: how do you manage screens, how do you navigate through them, and how do you manage the display and the input devices? The answer is that all this functionality is implemented by the Display class, which includes methods for requesting that objects be displayed on the device, and for retrieving properties of the device.

Display

A reference to the device's display can be obtained by providing a MIDlet reference to the static getDisplay( ) method.

public static Display getDisplay(MIDlet c);

This is typically done in the startApp( ) method of a MIDlet, as follows:

TIP: The getDisplay( ) method should be called after the beginning of the MIDlet's startApp( ) method, as shown earlier. It should never be called from the MIDlet's constructor, as per the MIDP specification, as it may not be properly initialized by the application manager at that time.

After you obtain a reference to the device's display, you simply need to create a GUI component to show. Note that all of the GUI components in Figure 5-2 implement the Displayable abstract class. You can pass the GUI component you create to one of Display's two setCurrent( ) methods:

The second method is used when you want to show a temporary alert message followed by the displayable GUI element. We'll discuss alerts later on in this chapter.

To find out what is currently being displayed on the device, use the getCurrent( ) method, which returns a reference to the Displayable object that is currently being displayed.

public Displayable getCurrent( );

In addition, the Display class (which is really the manager of the device) provides two methods for querying the display to determine the types of colors it supports:

public void boolean inColor( );
public int numColors( );

The first method, isColor( ), returns a boolean: true if the device supports color and false if it only supports grayscale. The numColors( ) method returns an integer number of distinct colors supported by the device.

Screen

As we mentioned before, the basic unit of interaction between the user and the device is the screen, which is an object that encapsulates device-specific graphics user input. As you can see from the class diagram in Figure 1, there are four types of high-level screens, shown by the subclasses: TextBox, List, Alert, and Form.

Figure 1. Class diagram of the major classes in the lcdui package.

However, Screen is an abstract class with some functionality of its own. Every Screen can have two additional characteristics: a title and a ticker. The screen title is simply a String that appears above the screen contents. The ticker is a graphical component that appears above the title and can be used to scroll information across to the user. Both are optional, although the title will default to a standard string. If the ticker is omitted, it is not shown at all and the space is given instead to the screen. We'll discuss the Ticker component shortly. However, Figure 2 shows the relative positions of the title and the ticker properties in a Screen object.

Figure 2. Titles and tickers on a screen.

The following methods of the Screen class can be used to set and retrieve the title and the ticker, respectively.

Ticker

The Ticker class implements a tickertape, or a piece of text that runs continuously across the display. A ticker can be attached to one or more of the four screens discussed earlier, namely: Alert, TextBox, List, and Form. To create a ticker object, use the Ticker constructor:

public Ticker(String str);

You can access the string used in the ticker with the following methods:

public String getString( );
public void setString(String s);

Once a ticker is created, it can be attached to a screen using the screen's setTicker( ) method. For example, the following snippet of code creates a List screen and attaches a ticker to it:

Figure 3 shows what a ticker looks like. It is located above the List component in the display.

Figure 3. An example of a ticker.

There are a few points to note about a ticker:

No method calls are provided for starting and stopping the ticker.

The ticker string scrolls continuously. In other words, when the string finishes scrolling off the display, the ticker starts over at the beginning of the string. It may help to add some spaces at the end of the ticker string so the message ends do not appear tied together.

The direction and the speed of the scrolling are determined by the MIDP implementation.

TextBox

A TextBox object is a screen that allows the user to enter and edit text. You can use a TextBox if your MIDlet needs some kind of input such as a name, a phone number, an email address, or a password. To create a TextBox object, you need to specify four parameters, as shown in the TextBox's constructor:

The title is reused as the screen title, while the text and maxSize are used to determine the initial (or default) text and maximum size of the text box. Finally, constraints can be used to limit the user's input. The constraints used are static constant integers of the TextField class, which are shared between TextField and TextBox, and are as follows:

TextField.ANY

The user is allowed to enter any character.

TextField.EMAILADDR

Input must be an email address.

TextField.NUMBER

Input must be an integer value.

TextField.PASSWD

The text entered will be masked (replaced by asterisks), so the characters typed are not visible.

TextField.PHONENUMBER

Input must be a phone number.

TextField.URL

Input must be a URL.

If you use a constraint other than TextField.ANY, the implementation will perform validation to make sure that the characters that are input conform to the requested type. (For example, TextField.NUMBER will not allow letters to be entered.) This is the only validation that is performed.

Note that the TextField.PASSWD constraint can be combined with any of the other constraints using the bitwise OR "|" operator. For example, if you wanted to create a TextBox that constrained input to a phone number but also wanted to keep the entered data hidden, you would create the object as follows:

If you wish to set or retrieve the current constraints that are active for the TextBox, use the following methods:

public int getConstraints( );
public void setConstrants(int c);

Another thing that we should point out is that a text box has a capacity, or a maximum size, which is the number of characters of text that it can hold. However, each MIDP implementation may place a boundary on the maximum size, which could be smaller than the size the application requested. The maximum size imposed by the implementation can be retrieved using the getMaxSize( ) method and (potentially) reset using the setMaxSize( ) method.

public int getMaxSize( );
public void setMaxSize(int size);

A well-written MIDP application should always compare the requested size against the current maximum size.

In the current MIDP reference implementation from Sun Microsystems, getMaxSize( ) always returns the requested size by the MIDlet. But don't let that get you out of the habit of checking.

You can set or retrieve the entire text in the TextBox with the setString( ) and getString( ) methods:

public String getString( );
public void setString(String s);

In addition, if you would like to see the number of characters in the text that has been entered, use the size( ) method, which returns an integer:

public int size( );

You can also manipulate the text in the TextBox quite easily by deleting, inserting, or replacing the current text using the following methods:

Finally, if you want to find out which position the caret, also known as the insertion beam, is currently in front of, TextBox includes the following method:

public int getCaretPosition( );

Here's a simple example. The following snippet of code creates a TextBox object with the label "TextBox" and initial text set to "This is a text box". The maximum size is 20 characters, which can be any type of characters.

If you write a complete MIDlet and run it in an emulator, you will see something similar to Figure 4. Note that if the text to be displayed is larger than the size of one screen, the implementation will let the user scroll to view and edit any part of the text. How this is done is implementation-dependent.