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.
These are also discussed in the MIDP Specifications.
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
List or TextBox component. The structure of these screens
is predefined, and the application cannot add other components to these screens.
- Generic screens that use a
Form component. 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
Canvas class.
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:
Alert
Command
DateField
Display
Displayable
Form
Gauge
List
TextBox
TextField
Ticker
CommandListener
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, developed using the Wireless Toolkit, 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:
INFO
WARNING
ERROR
ALARM
CONFIRMATION
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
Canvas class.
- 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 machine1 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.
Back To Top
|
|