MIDP GUI Programming: Programming the Phone Interface
by Qusay H. Mahmoud
Release 1.0
December 2000

The user interface requirements for handheld devices are different from those for desktop computers. For example, the display size of handheld devices is smaller, and the input devices do not always include pointing devices, for example, a mouse or pen input). For these reasons, you cannot follow the same user interface programming guidelines for applications running on desktop computers and hand-held devices.
The CLDC provides foundation classes for all resource-constrained Java-enabled handheld devices and needs to be complemented by profiles. For example, the CLDC itself does not define any Graphical User Interface (GUI) functionality. Official GUI classes for the Java 2 Micro Edition (J2ME) are defined by the Java Community Process (JCP) and are included in profiles such as the Mobile Information Device Profile (MIDP). The GUI classes included in the MIDP are not based on the Abstract Window Toolkit (AWT).
This article discusses the details of GUI programming for handheld devices. Because the MIDP GUI classes are not based on the AWT, this article starts with a brief discussion of why the MIDP Expert Group made that decision. That discussion is followed by a description of the GUI classes included in the MIDP with examples of how to use them. This article concludes with guidelines to GUI programming for mobile information devices.
Why not the AWT?
The MIDP Expert Group decided not to subset the existing AWT and Project Swing classes for the following reasons:
- The AWT is designed for desktop computers and optimized for these devices.
- The AWT assumes certain user interaction models. The component set of the AWT is designed to work with a pointing device such as a mouse; however many handheld devices, such as cell phones, have only a keypad for user input.
- While the AWT has a rich feature set, it is mainly desktop-based. Also, the feature set includes support for features not found on handheld devices. For example, the AWT has extensive support for window management, such as resizing overlapping windows. However, the limited display size of handheld devices makes resizing a window impractical. Therefore, the window and layout managers within the AWT are not required for handheld devices.
- When a user interacts with an AWT-based application, event objects are created dynamically. These objects exist only until each associated event is processed by the system, at which time the object becomes eligible for garbage collection. The limited CPU and memory of handheld devices cannot handle this behavior.
Structure of the MIDP User Interface API
The MIDP UI consists of high-level and low-level APIs.
High-Level API
The high-level API is designed for applications whose client parts run on mobile information devices where portability is important. To achieve portability, the API employs a high-level abstraction and gives you little control over its look and feel. For example, you cannot define the visual appearance (shape, color, or font) of components. Interaction with components is encapsulated by the implementation and the application is not aware of such interactions.
When you use the high-level API, the underlying implementation does the necessary adaptation to the device's hardware and native user interface style. The high-level API is implemented by classes that inherit from the Screen class.
Low-Level API
The low-level API provides little abstraction. It is designed for applications that need precise placement and control of graphic elements and access to low-level input events. This API gives the application full control over what is being drawn on the display. The Canvas and Graphics classes implement the low-level API.
It is important to note that MIDlets that access the low-level API are not guaranteed to be portable because this API provides mechanisms to access details that are specific to a particular device.
The MIDP GUI Programming Model
The central abstraction of the MIDP UI is a screen, which is an object that encapsulates device-specific graphics rendering user input. Only one screen can be visible at a time, and the user can traverse only through the items on that screen.
The main reason for the screen-based design is that mobile information devices have different display and keypad solutions. If an application has to be aware of component layout, scrolling, and focus traversal it compromises portability.
There are three types of screens:
- Screens that encapsulate a complex user interface component that involves a
ListorTextBoxcomponent. The structure of these screens is predefined, and the application cannot add other components to these screens. - Generic screens that use a
Formcomponent. The application can add text, images, and a simple set of related UI components to the form. - Screens used within the context of the low-level API, such as a subclass of the
Canvasclass.
The Display class is the display manager that is instantiated for each active MIDlet and provides methods to retrieve information about the device's display capabilities. A screen is made visible by calling the Display.setCurrent() method.
The lcdui Package
All MIDP GUI classes are in the lcdui package. To use the GUI classes, your MIDlets have to import this package as follows:
import javax.microedition.lcdui.*;
The lcdui package contains the following three interfaces and twenty one classes described in alphabetical order in the following table:
| Interfaces | Description |
|---|---|
Choice |
Defines an API for a user interface component that implements selections from a predefined number of choices. |
CommandListener |
Used by applications that need to receive high-level events from the implementation. |
ItemStateListener |
Used by applications that need to receive events that indicate changes in the internal state of the interactive items. |
| Classes | Description |
|---|---|
Alert |
A screen that shows data to the user and waits for a certain period of time before proceeding to the next screen. |
AlertType |
Indicates the nature of the alerts. |
Canvas |
The base class for writing applications that need to handle low-level events and to issue graphics calls for drawing to the display. |
ChoiceGroup |
A group of selectable elements intended to be placed within a Form. |
Command |
A construct that encapsulates the semantic information of an action. |
DateField |
An editable component for presenting calendar date and time information that may be placed into a Form. |
Display |
Represents the manager of the display and input devices of the system. |
Displayable |
An object that has the capability of being placed on the display. |
Font |
Represents fonts and font metrics. |
Form |
A screen that contains an arbitrary mixture of items (images, text, text fields, choice groups, for instance.) |
Gauge |
Implements a bar graph display of a value intended for use in a form. |
Graphics |
Provides simple 2D geometric rendering capability. |
Image |
Holds graphical image data. |
ImageItem |
Provides layout control when Image objects are added to a Form or Alert. |
Item |
A superclass for components that can be added to a Form or Alert. |
List |
A screen containing a list of choices. |
Screen |
The superclass of all high-level user interface classes. |
StringItem |
An item that can contain a string. |
TextBox |
A screen that allows the user to enter and edit text. |
TextField |
An editable text component that can be placed into a Form. |
Ticker |
A ticker-type piece of text that runs continuously across the display. It can be attached to all screen types except Canvas. |
Example
This example demonstrates how to create various GUI components. The MIDlet for this example allows you to test lists, forms, choices, gauges, text fields, text boxes, for instance.
The GuiTests MIDlet has a few methods for testing various GUI components. The MIDlet makes use of the following classes, listed in alphabetical order, from the javax.microedition.lcdui package:
AlertCommandDateFieldDisplayDisplayableFormGaugeListTextBoxTextFieldTickerCommandListener
Here is the source code for this example:
Listing1: GuiTests.java
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class GuiTests extends MIDlet
implements CommandListener {
// display manager
Display display;
// a menu with items
// main menu
List menu;
// list of choices
List choose;
// textbox
TextBox input;
// ticker
Ticker ticker = new Ticker(
"Test GUI Components");
// alerts
final Alert soundAlert =
new Alert("sound Alert");
// date
DateField date = new DateField("Today's date: ", DateField.DATE);
// form
Form form = new Form("Form for Stuff");
// today's form
Form today = new Form("Today's date");
// gauge
Gauge gauge = new Gauge("Progress Bar", false, 20, 9);
// text field
TextField textfield = new TextField(
"TextField Label", "abc", 50, 0);
// command
static final Command backCommand =
new Command("Back", Command.BACK, 0);
static final Command mainMenuCommand =
new Command("Main", Command.SCREEN, 1);
static final Command exitCommand =
new Command("Exit", Command.STOP, 2);
String currentMenu;
// constructor.
public GuiTests() {
}
/**
* Start the MIDlet by creating a list of
* items and associating the
* exit command with it.
*/
public void startApp() throws
MIDletStateChangeException {
display = Display.getDisplay(this);
menu = new List(
"Test Components", Choice.IMPLICIT);
menu.append("Test TextBox", null);
menu.append("Test List", null);
menu.append("Test Alert", null);
menu.append("Test Date", null);
menu.append("Test Form", null);
menu.addCommand(exitCommand);
menu.setCommandListener(this);
menu.setTicker(ticker);
mainMenu();
// form
form.append(gauge);
form.append(textfield);
// today
today.append(date);
}
public void pauseApp() {
display = null;
choose = null;
menu = null;
ticker = null;
form = null;
today = null;
input = null;
gauge = null;
textfield = null;
}
public void destroyApp(boolean unconditional) {
notifyDestroyed();
}
// main menu
void mainMenu() {
display.setCurrent(menu);
currentMenu = "Main";
}
/**
* Test the TextBox component.
*/
public void testTextBox() {
input = new TextBox
("Enter Some Text:", "", 10, TextField.ANY);
input.setTicker(new Ticker(
"Testing TextBox"));
input.addCommand(backCommand);
input.setCommandListener(this);
input.setString("");
display.setCurrent(input);
currentMenu = "input";
}
/**
* Test the List component.
*/
public void testList() {
choose = new List("Choose Items",
Choice.MULTIPLE);
choose.setTicker(new Ticker(
"Testing List"));
choose.addCommand(backCommand);
choose.setCommandListener(this);
choose.append("Item 1", null);
choose.append("Item 2", null);
choose.append("Item 3", null);
display.setCurrent(choose);
currentMenu = "list";
}
/**
* Test the Alert component.
*/
public void testAlert() {
soundAlert.setType(AlertType.ERROR);
//soundAlert.setTimeout(20);
soundAlert.setString("** ERROR **");
display.setCurrent(soundAlert);
}
/**
* Test the DateField component.
*/
public void testDate() {
java.util.Date now = new java.util.Date();
date.setDate(now);
today.addCommand(backCommand);
today.setCommandListener(this);
display.setCurrent(today);
currentMenu = "date";
}
/**
* Test the Form component.
*/
public void testForm() {
form.addCommand(backCommand);
form.setCommandListener(this);
display.setCurrent(form);
currentMenu = "form";
}
/**
* Handle events.
*/
public void commandAction(Command c,
Displayable d) {
String label = c.getLabel();
if (label.equals("Exit")) {
destroyApp(true);
} else if (label.equals("Back")) {
if(currentMenu.equals("list")
|| currentMenu.equals("input") ||
currentMenu.equals("date")
|| currentMenu.equals("form")) {
// go back to menu
mainMenu();
}
} else {
List down = (List)display.getCurrent();
switch(down.getSelectedIndex()) {
case 0: testTextBox();break;
case 1: testList();break;
case 2: testAlert();break;
case 3: testDate();break;
case 4: testForm();break;
}
}
}
}
Testing the GuiTests MIDlet
To test the GuiTests MIDlet, do the following:
- Create a new project (call it
TestGUI) and a MIDlet class (call it GuiTests), copy the code to the appropriate location, and compile it. -
Run the MIDlet in the emulator.
You see a TestGUI MIDlet running as shown in Figure 1.
Figure 1: TestGUI
Note: For more information about testing MIDlets using the Wireless Toolkit, see the Quick Start to the Wireless Toolkit.
-
Activate the TestGUI.
The MIDlet runs and you see a menu with the following options: Test TextBox, Test List, Test Alert, Test Date, and Test Form, as shown in Figure 2.
Figure 2: TestGUI components
- Choose a test to perform.
Choosing the Tests
These are the tests from the UITest MIDlet.
Figure 3: The TextBox, List, and Alert tests
If you have a soundcard, you hear a warning sound with the Alert.
An alert is a screen that shows data to the user and waits for a certain period of time (which can be set using setTimeout) before proceeding to the next screen. An alert may have an alert type. In this example the alert is type ERROR. The predefined types all play appropriate sounds when invoked and are the following:
INFOWARNINGERRORALARMCONFIRMATION
Figure 4: DateField, Calendar, and Form with Gauge and TextField
The Gauge class implements a bar graph display that can be either interactive or non-interactive. The value of the gauge can be retrieved by the application at any time. The visual appearance and value of the bar graph can be changed if it is in interactive mode.
Guidelines for Programming UI for MID Devices
Here are some guidelines to keep in mind when designing MIDlets:
- Make the MIDlets' user interface simple and easy to use.
- Use the high-level API so your MIDlets are portable across handheld devices.
- If your application requires you to use the low-level API, keep to the platform-independent part of the low-level API. This means your MIDlets should not assume any other keys than defined in the the
Canvasclass. - MIDlets should not depend on any specific screen size; they should query the size of the display and adjust accordingly.
- Entering data through a handheld device can be tedious. If possible, provide a list of choices that the user can select from.
- Avoid using third-party user class libraries such as the kAWT, which is a simplified version of the the AWT for the KVM.
Conclusion
The MIDP User Interface API is not a subset of the AWT/Swing libraries. J2ME provides a set of simple UI components. Programming with these components is easy in comparison with the J2SE AWT and Project Swing libraries because the MIDP GUI API is simpler. There are only two dozen classes you need to learn.
There are ongoing projects outside Sun Microsystems to develop a simplified version of the AWT (for example, the kAWT) enabling parallel development for the Java virtual machine 1 and JKVM. However, these have tradeoffs, such as portability and memory requirements.
More Information
About the Author: Qusay H. Mahmoud provides Java consulting and training services. He has published dozens of articles on Java, and is the author of Distributed Programming with Java (Manning Publications, 1999) and Learning Wireless Java (O'Reilly & Associates, 2002).
1 As used in this document, the terms "Java virtual machine" or "JVM" mean a virtual machine for the Java platform.