January 26, 2021
Hot Topics:

MIDP Programming with J2ME

  • By Sams Publishing
  • Send Email »
  • More Articles »

Receiving Changes from Interactive UI Items

If you run the new version of the TeleTransfer MIDlet, you can change the currency using the ChoiceGroup, but the TextField labels for Dollar and Cent are not changed accordingly. You need a way to notify the application if a selection is made in the currency ChoiceGroup.

Receiving changes of interactive high-level UI items in MIDP is based on a listener model similar to AWT. Classes implementing the ItemStateListener interface are able to receive notifications for the following events:

  • State changes of a ChoiceGroup

  • Value adjustments of an interactive Gauge

  • TextField value changes

  • DateField changes

The events are sent to the method itemStateChanged() of the ItemStateListener, where the item that has changed is given as a parameter. In order to actually receive these events, the ItemStateChangeListener must be registered using the setItemStateListener() method of the corresponding Form.

Now that you know about item state change events, you can add the desired functionality to your TeleTransfer MIDlet. First, you need to add the ItemStateListener interface to the class declaration:

public class TeleTransfer extends MIDlet implements ItemStateListener {

You also need to implement a corresponding itemStateChanged() method. Since the itemStateChanged() method is called for changes of all Items in the Form, you need to check the item parameter indicating the event source first. If the source of the event is the currency ChoiceGroup, you set the labels of the amount and fraction TextFields correspondingly:

public void itemStateChanged (Item item) {
  if (item == currency) {
    int index = currency.getSelectedIndex ();
    switch (index) {
    case 0: amountWhole.setLabel ("Dollar");
         amountFraction.setLabel ("Cent");
    case 1: amountWhole.setLabel ("Euro");
        amountFraction.setLabel ("Cent");
    case 2: amountWhole.setLabel ("Yen");
        amountFraction.setLabel ("Sen");

Just adding the interface and implementing the corresponding methods is not sufficient to enable the MIDlet to receive state changes. Additionally, you need to register your ItemStateListener at the Form containing the currency item. You do so by calling the setItemStateListener() method in the TeleTransfer constructor:

public TeleTransfer () {
  mainForm.append (senderAccount);
  mainForm.append (currency);
  mainForm.setItemStateListener (this);

Figure 3.5 shows the new version of the TeleTransfer example, where the labels are changed depending on the state of the currency ChoiceGroup.

Figure 3.5 The TeleTransfer MIDlet extended to change the labels depending on the state of the currency ChoiceGroup.

Using Commands for User Interaction

Now you can enter all the information required for a telegraphic transfer, but you have no means to initiate the actual transfer.

In contrast to desktop computers, which have plenty of screen space for displaying buttons or menus, a different approach is necessary for mobile devices. Some devices provide so-called soft buttons, which are buttons without fixed functionality that are assigned dynamically depending on the application context. The number of soft buttons may vary if they are available. Other mobile devices do not even have space for soft buttons, but provide scrolling menus. MIDP needs to abstract from the concrete device and to provide a mechanism that is suitable for all devices, independent of the availability and number of soft buttons. Thus, the lcdui package does not provide buttons or menus, but an abstraction called Command.

Commands can be added to all classes derived from the Displayable class. These classes are Screen and its subclasses such as Form, List, and TextBox for the high-level API and Canvas for the low-level API.

No positioning or layout information is passed to the Command—the Displayable class itself is completely responsible for arranging the visible components corresponding to Commands on a concrete device. The only layout and display information that can be assigned to a Command except from the command label is semantic information. The semantic information consists of a type and a priority. The priority allows the device to decide which commands are displayed as soft buttons if the number of commands exceeds the number of soft buttons available. For additional commands not displayed as soft buttons, a separate menu is created automatically. The type information is an additional hint for the device about how to display the command. For example, if the Exit command is always assigned to the leftmost soft button in native applications of a certain device type, the MIDP implementation is able to make the same assignment. Thus, a consistent look and feel can be accomplished for a device.

The available command type constants are listed in Table 3.5.

Table 3.5 Command Type Constants




Used for navigation commands that are used to return the user to the previous Screen.


Needed to notify the screen that a negative answer occurred.


Used to specify a Command for exiting the application.


Passed when the application requests a help screen.


A command type to tell the application that it is appended to an explicit item on the screen.


Needed to notify the screen that a positive answer occurred.


A type that specifies a screen-specific Command of the application.


Interrupts a procedure that is currently running.

The Command constructor takes the label, the command type and the priority as input. The Command class provides read() methods for all these fields, but it is not possible to change the parameters after creation. Using the addCommand() method, commands can be added to a Form or any other subclass of Displayable.

As in the case of receiving state changes of UI widgets, the MIDP uses a listener model for detecting command actions. For this purpose, the lcdui package contains the interface CommandListener. A CommandListener can be registered to any Displayable class using the setCommandListener method. After registration, the method commandAction() of the Commandlistener is invoked whenever the user issues a Command. In contrast to AWT, only one listener is allowed for each Displayable class. The commandAction() callback method provides the Displayable class where the command was issued and the corresponding Command object as parameters.

With this information, you can extend your TeleTransfer application with the desired Commands. But before going into actual command implementation, you need to add some corresponding functionality. You'll add three commands: a Send command, a Clear command, and an Exit command. For Clear, you just add a method setting the content of the fields of your form to empty strings:

public void clear () {
receiverName.setString ("");
receiverAccount.setString ("");
amountWhole.setString ("");
amountFraction.setString ("");

The Send command is a bit more difficult since you do not yet have the background to really submit information over the network. (Network connections will be handled in Chapter 6, "Networking: The Generic Connection Framework.") So you just display the content to be transmitted in an alert screen as a temporary replacement:

public void send () {
  Alert alert = new Alert ("Send");
  alert.setString ("transfer " + amountWhole.getString () 
           + "." + amountFraction.getString () + " " 
           + amountWhole.getLabel ()
           + "\nto Acc#" + receiverAccount.getString () 
           + "\nof " + receiverName.getString ());
  alert.setTimeout (2000);
  display.setCurrent (alert);
  clear ();

For leaving the application, the MIDlet already provides the notifyDestroyed() method, so you do not need to add anything here.

Now that you have implemented the corresponding functionality, the next step is to add the actual Command objects to your application class:

static final Command sendCommand = new Command ("Send", Command.SCREEN, 1);
static final Command clearCommand = new Command ("Clear", Command.SCREEN, 2);
static final Command exitCommand = new Command ("Exit", Command.EXIT, 2);

In order to enable the MIDlet to receive command actions, you need to implement the CommandListener interface, and the corresponding commandAction() method. Depending on the command received, you call send(), clear(), or notifyDestroyed():

public class TeleTransfer extends MIDlet 
  implements ItemStateListener, CommandListener {

public void commandAction (Command c, Displayable d) {
  if (c == exitCommand) {
  else if (c == sendCommand) {
    send ();
  else if (c == clearCommand) {
    clear ();

With these modifications, your TeleTransfer MIDlet is able to handle the desired commands. You still need to add the Commands to the Form, and register the TeleTransfer MIDlet as a CommandListener in order to actually receive the commands:

public TeleTransfer () {
  mainForm.addCommand (sendCommand);
  mainForm.addCommand (clearCommand);
  mainForm.addCommand (exitCommand);
  mainForm.setCommandListener (this);

Figure 3.6 shows the Send Alert of the new version of your TeleTransfer application.

Figure 3.6 The TeleTransfer MIDlet showing an alert that displays the transfer information as a summary before sending.

Further Item Classes: Gauge and DateField

Now you have used all the Item subclasses except Gauge and DateField. Both classes are specialized input elements, where the Gauge may also make sense as a pure read-only information item.

The Gauge item visualizes an integer value by displaying a horizontal bar. It is initialized with a label, a flag indicating whether it is interactive, and a maximum and an initial value. If a Gauge is interactive, the user is allowed to change the value using a device-dependent input method. Changes to the gauge value will cause ItemEvents if a corresponding listener is registered to the form.

The following code snippet shows the construction of a non-interactive Gauge labeled Progress that is initialized with a value of 0 and a maximum of 100:

Gauge gauge = new Gauge ("Progress", false, 0, 100);

If a Gauge is used to display progress of a process that takes a longer amount of time, you should also add a corresponding Stop command to the form to abort the progress.

The current value of the Gauge can be set using the method setValue() and read using the method getValue(). Analogous setMaxValue() and getMaxValue() methods let you access the maximum value of the Gauge.

The DateField is a specialized widget for entering date and time information in a simple way. It can be used to enter a date, a time, or both types of information at once. The appearance of the DateField is specified using three possible input mode constants in the constructor. Possible DateField mode constants are listed in Table 3.6.

Table 3.6 DateField Mode Constants




Passed if the DateField should be used for entering a date only.


Used for creating a DateField to enter both date and time information.


Used to enter time information only.

The DateField has two constructors in which a label and the mode can be specified. Using the second constructor, an additional TimeZone can be passed. The following code snippet shows how a DateField for entering the date of birth can be initialized:

DateField dateOfBirth = new DateField ("Date of birth:", DateField.DATE);

After you enter the date into the DateField, it can be accessed using the getDate() method. The DateField offers some additional methods for getting information about the input mode and methods for setting the date and the input mode as well. The concrete usage of the DateField is shown in Chapter 9 in the Blood Sugar Logger application.

Page 3 of 8

This article was originally published on December 26, 2002

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date