The Lightweight User Interface Toolkit (LWUIT): An Introduction

   
By Jonathan Knudsen, September 2008  

Articles Index

The Lightweight User Interface Toolkit (LWUIT) is a versatile and compact API for creating attractive application user interfaces for mobile devices. LWUIT provides sophisticated Swing-like capabilities without the tremendous power and complexity of Swing. Designed from the ground up as an efficient mobile user interface toolkit, LWUIT provides many useful Swing-like features.

LWUIT offers a basic set of components, flexible layouts, style and theming, animated screen transitions, and a simple and useful event-handling mechanism. The toolkit has been tested and debugged on a variety of mobile devices.

This tutorial is designed to get you up and running with LWUIT in as little time as possible. It assumes that you are using version 6.1 or later of the NetBeans IDE, a version that includes mobility support. The examples and screen captures in the tutorial were run on the Sprint Wireless Toolkit, but you can use the Sun Java Wireless Toolkit emulator as well.

Contents
 
Hello, LWUIT!
Working With Forms
Filling Forms With Components
Using Layouts
Using Transitions
Event Handling
Using Commands
Styles and Themes
Changing All Components With Themes
Conclusion
About the Author
For More Information
 
Hello, LWUIT!

To get started right away, follow these steps.

  1. Download the LWUIT ZIP file to your computer and uncompress it.

  2. Create a new project in the NetBeans IDE. Choose File > New Project... from the menu. Then, choose the Mobility category and MIDP Application project, and press Next >, as shown in Figure 1.

     
    Figure 1: A New Project in the NetBeans IDE
     
  3. Now enter a name for the project, such as HelloLWUIT, as shown in Figure 2. Choose a location and make sure to deselect Create Hello MIDlet. Then, press Next > (not Finish.)

     
    Figure 2: Enter a Name for the Project
     
  4. Finally, for the emulator platform, choose either Sun Java Wireless Toolkit 2.5.2 for CLDC or (if it is installed) Sprint Wireless Toolkit 3.2 Powered by Sun Java Technology, depending on which is your favorite. DefaultColorPhone, CLDC-1.1, and MIDP-2.1 are the correct default choices for this dialog box. See Figure 3. Then, press Finish to create the project.

     
    Figure 3: Choose the Default Platform
     
  5. Add LWUIT to the project. In the project you just created, right-click on Resources. Click on the Add Jar/Zip... button and navigate to the LWUIT JAR file, which should be in the base directory of the LWUIT ZIP file you just uncompressed.

  6. Write a simple application. Right-click on your project and choose New > MIDlet from the menu. Enter a name, like HelloLWUITMIDlet, and press Finish.

Here is the source code for a simple LWUIT MIDlet. Type it in, or copy and paste it.

import javax.microedition.midlet.*;

import com.sun.lwuit.*;
import com.sun.lwuit.events.*;

public class HelloLWUITMidlet extends MIDlet implements ActionListener {
  public void startApp() {
   Display.init(this);

   Form f = new Form("Hello, LWUIT!");

   f.show();

   Command exitCommand = new Command("Exit");
   f.addCommand(exitCommand);
   f.setCommandListener(this);
  }

  public void pauseApp() {}

  public void destroyApp(boolean unconditional) {}

  public void actionPerformed(ActionEvent ae) {
   notifyDestroyed();
  }
}

 

At this point, you can compile and run the application. In the NetBeans IDE, just press F6 to compile and run. A device emulator will pop up with your application. The text "Hello, LWUIT!" appears as the title of the form, and "Exit" is at the bottom of the screen, as shown in Figure 4. Congratulations! Press F1 to finish.

 
Figure 4: Hello LWUIT Running on the Sprint Emulator
 

The LWUIT Java Theme in the Sun Emulator

If you are using the Sun emulator, the first thing you'll likely notice is that the background is very sparse. The following examples use the LWUIT Java Theme, which is contained deep in the distribution under the filename javaTheme.res.

If you would like to use that theme for the purposes of these examples instead of creating your own theme with the LWUIT ResourceEditor tool, copy the javaTheme.res file into a directory called res, compress the res directory and its contents into a ZIP file, then add the ZIP file to the Resources of your project just as you did with the LWUIT JAR earlier. Finally, insert the following code in your startApp() method:

try {
  Resources r = Resources.open("/res/javaTheme.res");
  UIManager.getInstance().setThemeProps(r.getTheme("javaTheme"));
} catch (IOException ioe) {
  // Do something here.
}
 
 
Working With Forms

You must initialize LWUIT before you can use it in your application. To do this, call Display's static init() method, passing in the application object. For example, in a MIDlet's startApp() method, initialize LWUIT like this:

Display.init(this);
 

Your application will interact with users by showing one or more forms on the screen. A form has a title and perhaps a menu bar, and it can contain a wide variety of visual components. Figure 5 shows the three areas of a form.

 
Figure 5: A LWUIT Form
 

This code creates a single empty form with a title.

Form f = new Form("Hello, LWUIT!");
 

To show a form on the screen, just call the show() method.

f.show();
 
Filling Forms With Components

LWUIT offers a comprehensive toolbox for showing information on forms and receiving user input, including many familiar components such as labels, buttons, and lists. Simply create the components you want to use and pass them to the form's addComponent() method.

The simplest component is a label. A label can display text, an image, or both. Here are a few examples:

//Form f = ...

Label label = new
Label("Baldy");
f.addComponent(label);

Image image = Image.createImage("/res/baldy.png");
Label pictureLabel = new Label(image);
f.addComponent(pictureLabel);

Label bottomText = new Label(image);
bottomText.setText("Baldassare");
bottomText.setTextPosition(Component.BOTTOM);
f.addComponent(bottomText);
 

The result of this code is shown in Figure 6.

 
Figure 6: A Form With Labels and Images
 

Buttons are similar to labels, but the user can "click" on them. The exact details of clicking depend on the device. For example, on a device with a touch screen, the user can simply touch the button. On devices with four-way navigation, the user can move focus to the button, then press the Select key.

The Button class inherits from the Label class. Here are a few examples:

//Form f = ...
Button button = new Button("Baldy");
f.addComponent(button);

Image image = Image.createImage("/res/baldy.png");
Button pictureButton = new Button(image);
f.addComponent(pictureButton);

Button combined = new Button("Baldassare", image);
combined.setTextPosition(Component.BOTTOM);
f.addComponent(combined);
 

The results are shown in Figure 7.

 
Figure 7: A Form With Buttons
 

Later in this tutorial, you'll learn how to respond to button events. The button takes care of showing visual cues to indicate focus and pressing.

Subclasses of the Button class represent checkboxes and radio buttons. ButtonGroup is used to manage groups of exclusive radio buttons. The following example shows one way to add checkboxes and radio buttons to a form. It uses a layout to keep the components neatly lined up. You'll read about layouts later in this tutorial.

Form f = new Form("More Buttons");
f.setLayout(new BoxLayout(BoxLayout.Y_AXIS));

RadioButton rb;
ButtonGroup group = new ButtonGroup();

rb = new RadioButton("Grilled chicken");
group.add(rb);
f.addComponent(rb);

rb = new RadioButton("Filet mignon");
group.add(rb);
f.addComponent(rb);

rb = new RadioButton("Mahi mahi");
group.add(rb);
f.addComponent(rb);

rb = new RadioButton("Chili");
group.add(rb);
f.addComponent(rb);

CheckBox cb;

cb = new CheckBox("Guacamole");
f.addComponent(cb);

cb = new CheckBox("Tabasco sauce");
f.addComponent(cb);

cb = new CheckBox("Mango salsa");
f.addComponent(cb);

cb = new CheckBox("Mayonnaise");
f.addComponent(cb);

cb = new CheckBox("Whipped cream");
f.addComponent(cb);
 

The result of this code is shown in Figure 8.

 
Figure 8: Using Buttons and Checkboxes
 

Two components for showing lists of items are List and ComboBox. Both use a ListModel to contain the data that is displayed. You can use the default list model, which is sufficient for many applications, or you can create your own. Like Swing, LWUIT uses the model-view-controller paradigm for a clean separation of the data, its presentation, and user interactions.

This example shows how to create a simple list. Behind the scenes, a ListModel is created automatically. The combo box uses the same ListModel. When you make a selection in the list or the combo box, the other component is automatically updated to match.

//Form f = ...
List list = new List();
list.addItem("uno");
list.addItem("due");
list.addItem("tre");
list.addItem("quattro");
list.addItem("cinque");
list.addItem("sei");
f.addComponent(list);

ComboBox comboBox = new ComboBox(list.getModel());
f.addComponent(comboBox);
 

Figure 9 shows the results of the list and the combo box.

 
Figure 9: LWUIT Lists and Combo Boxes
 

Another commonly used component is a TextArea, which displays text that users can edit. Text is displayed directly on your form, but the user enters text input on a separate screen. LWUIT provides editing on a separate screen to take advantage of whatever predictive text mechanisms are available on the device. This happens transparently as far as your application is concerned. All your application has to do is add a TextArea to a form. LWUIT takes care of handling user interactions for editing.

This example shows how to create a simple text area -- more like a field -- by specifying the initial text. It also shows how to create a larger text area by specifying the number of visible rows and columns.

//Form f = ...
TextArea area = new TextArea("Peppino");
f.addComponent(area);

TextArea big = new TextArea("On February 24, 1815, the lookout at " +
  "Notre-Dame de la Garde signalled the arrival of the three-master " +
  "Pharaon, coming from Smyrna, Trieste and Naples.", 5, 20);
f.addComponent(big);
 

The result is shown in Figure 10.

 
Figure 10: TextAreas in LWUIT
 

LWUIT includes several other components that are not described in this tutorial, such as the following:

  • Calendar displays a calendar and allows the user to choose a day.

  • TabbedPane is a special container that represents panes of information with selectable tabs.

  • MediaComponent is used to display rich media content.

Using Layouts

The form takes care of positioning the components. It uses a layout manager to decide where everything goes. For you AWT and Swing developers, this should sound familiar. Layout managers are great for mobile applications because they are good at adjusting to different screen sizes and filling the available space gracefully.

LWUIT includes five layout managers.

  • FlowLayout places components from left to right in rows, just like English text.

  • BorderLayout has a large center area and four smaller areas around the edges.

  • BoxLayout arranges components in a single row or column.

  • GridLayout places components in a grid.

  • More complex layouts can be accomplished using GroupLayout and its helper class Group.

You can build user interfaces that combine layouts by creating Containers that group components with a specific layout and then nesting different Containers together to create a complete user interface.

A variant of Container's addComponent() method allows you to provide a hint, or constraint, that is used when determining the position of each component. For example, the five regions of a BorderLayout are represented by the static variables NORTH, SOUTH, EAST, WEST, and CENTER. To add a component to the WEST or left region, you would do this:

// Form f = ...
// Component c = ...
f.setLayout(new BorderLayout());
f.addComponent(BorderLayout.WEST, c);
 

The following example shows how to combine a BorderLayout and a BoxLayout. The CENTER region of the BorderLayout contains the main content, an image. The SOUTH region contains a button bar in an X_AXIS BoxLayout. Any components or containers placed in the center region stretch to fill the available space. In this case, the label is center-aligned so that the image appears in the center.

// Form f = ...
f.setLayout(new BorderLayout());

Image image = Image.createImage("/res/baldy.png");
Label bottomText = new Label(image);
bottomText.setAlignment(Component.CENTER);
bottomText.setText("Baldassare");
bottomText.setTextPosition(Component.BOTTOM);

Container buttonBar = new Container(new BoxLayout(BoxLayout.X_AXIS));
buttonBar.addComponent(new Button("Add"));
buttonBar.addComponent(new Button("Remove"));
buttonBar.addComponent(new Button("Edit"));
buttonBar.addComponent(new Button("Send"));
buttonBar.addComponent(new Button("Exit"));

f.addComponent(BorderLayout.CENTER,bottomText);
f.addComponent(BorderLayout.SOUTH, buttonBar);
 

The result is shown in Figure 11.

 
Figure 11: Combining a BorderLayout and a BoxLayout
 
Using Transitions

Many applications use more than one form. For example, a messaging application might use one screen to show incoming messages, a second screen for composing messages, and a third screen to display an address book.

To show more than one form in LWUIT, simply create forms and call each show() method when you want to display the corresponding form.

A transition provides a helpful visual cue to the user about the relationship between different forms. LWUIT can slide forms horizontally or vertically. LWUIT also includes a gradual fade from one form to the next. On devices with the JSR 184 Mobile 3D Graphics API, LWUIT can also perform some three-dimensional transitions.

If LWUIT's transitions don't meet your needs, you can write your own transition.

The CommonTransitions class contains static factory methods for creating slide and fade transitions:

  • createSlide() creates a transition that slides a new form onto the screen while sliding the current form off. Sliding can be up, down, left, or right.

  • createFade() makes a transition that smoothly fades from the current to a new one.

For devices that support the JSR 184 Mobile 3D Graphics API, LWUIT offers static methods in Transition3D for three additional types of transitions:

  • createFlyIn() zooms the new form in from the center to fill the entire screen.

  • createCube() gives the illusion that the current form is the front face of a cube. The cube rotates to show another face, which is the new form.

  • createRotation() flips the current form like a playing card. The new form is revealed on the other side.

You can set an incoming and outgoing transition for each form. The incoming transition is used when the form will be displayed. The outgoing transition is used when the form will be replaced by another.

The following example sets up two forms with a single button on each. Press the button to switch between the forms using slide transitions. You create the slide transitions by specifying whether the slide is horizontal or vertical, a direction ( true for forward, false for reverse), and the time in milliseconds.

In the example, the first form's outgoing transition is horizontal, backward (meaning that the form will slide off to the left), and 200 milliseconds long. The second form's outgoing transition is the same, but forward, which means it slides off to the right.

import javax.microedition.midlet.*;

import com.sun.lwuit.*;
import com.sun.lwuit.animations.*;
import com.sun.lwuit.events.*;

public class TransitionMIDlet extends MIDlet implements ActionListener {
  private Form mFirstForm, mSecondForm;

    public void startApp() {
     if (mFirstForm == null) {
      Display.init(this);

      mFirstForm = new Form("First Form");

      Button button = new Button("Switch");
      mFirstForm.addComponent(button);
      button.addActionListener(this);

      mFirstForm.setTransitionOutAnimator(
        CommonTransitions.createSlide(
          CommonTransitions.SLIDE_HORIZONTAL, false, 200));

      mSecondForm = new Form("Second Form");

      Button button2 = new Button("Switch");
      mSecondForm.addComponent(button2);
      button2.addActionListener(this);

      mSecondForm.setTransitionOutAnimator(
        CommonTransitions.createSlide(
          CommonTransitions.SLIDE_HORIZONTAL, true, 200));

      mFirstForm.show();
     }
    }

    public void pauseApp() {}

    public void destroyApp(boolean unconditional) {}

    public void actionPerformed(ActionEvent ae) {
     Form current = Display.getInstance().getCurrent();
     if (current == mFirstForm) {
      mSecondForm.show();
     } else if (current == mSecondForm) {
      mFirstForm.show();
     }
    }
}
 
Event Handling

Let's talk first about responding to button clicks. LWUIT notifies your application about events by way of listener interfaces. Your application provides implementations of the appropriate interface, registers them with LWUIT, and takes action when an event occurs.

To respond to a button press, for example, your application needs to do two things:

  1. Define an implementation of ActionListener

  2. Pass an instance of the ActionListener to the Button's addActionListener() method

The following example uses an inner class to implement ActionListener. Every time you press the button, the label changes.

final Form f = new Form("Events");

Button button = new Button("Push me!");
final Label countLabel = new Label(" ");
button.addActionListener(new ActionListener() {
  private int c = 0;
  public void actionPerformed(ActionEvent ae) {
    c++;
    countLabel.setText(Integer.toString(c));
    f.layoutContainer();
  }
});
 

The call to layoutContainer() ensures that the label's size is adjusted correctly when the number gets bigger. If you use a single listener for more than one button, you can find out which button was pressed by calling the ActionEvent's getSource() method.

Using Commands

LWUIT includes the concept of a command. A command is something that the user can do in your application. LWUIT decides how to show the command on the screen and how the user makes it happen. Usually, commands are assigned to the soft buttons on a mobile phone. LWUIT will normally show commands as labels at the bottom corners of the screen. The user can invoke them by pressing the corresponding soft button. On touch devices, the user can touch directly on a command to invoke it.

Conceptually, commands in LWUIT closely resemble commands in the Mobile Information Device Profile (MIDP). If you already understand MIDP commands, you'll have no trouble with LWUIT commands, which differ slightly in the details.

In LWUIT, create commands and add them to forms. Then register a listener object with the form to be notified when the user invokes a command.

The following simple example creates a form and registers a listener. The listener shuts down the application when it is invoked.

import javax.microedition.midlet.*;

import com.sun.lwuit.*;
import com.sun.lwuit.events.*;

public class HelloLWUITMidlet extends MIDlet implements ActionListener {

  private Form mForm;

  public void startApp() {
    if (mForm == null) {
      Display.init(this);

      Form f = new Form("Hello, LWUIT!");

      Command exitCommand = new Command("Exit");
      f.addCommand(exitCommand);
      f.setCommandListener(this);

      f.show();
    }
  }

  public void pauseApp() {
  }

  public void destroyApp(boolean unconditional) {
  }

  public void actionPerformed(ActionEvent ae) {
   destroyApp(true);
   notifyDestroyed();
  }
}
 

If you add more than two commands to a form, they won't fit on the two available soft buttons. In this case, one of the soft buttons will become a menu. When the user invokes the menu, it shows a list of the rest of the commands.

When your listener's actionPerformed() method must respond to more than one command, you can find out which one was invoked by calling the ActionEvent's getCommand() method.

Most of your event handling will involve ActionListener for commands and buttons, but LWUIT includes other useful listeners:

  • Use DataChangedListener to find out when a ListModel changes. Remember, ListModel represents the data behind a list or combo box.

  • A SelectionListener is notified when the current selection of a ListModel changes.

  • A FocusListener is notified when a component gains or loses focus.

  • A StyleListener receives notifications about changes in a component's style.

The next section of this tutorial describes styles and themes.

Styles and Themes

With LWUIT, you can change the style of components one by one. The visual appearance of every LWUIT component is determined, in part, by an associated style object. To make changes to an individual component's appearance, you can retrieve the style object and call methods to make changes.

Here is a simple example that modifies the style of some labels. The results are shown in Figure 12.

Label first = new Label("No style changes");
f.addComponent(first);
Label second = new Label("Transparent");
second.getStyle().setBgTransparency(0);
f.addComponent(second);
Label third = new Label("Purple");
Style style = third.getStyle();
style.setBgColor(0xaa00ff);
style.setFgColor(0xffffff);
f.addComponent(third);
 
 
Figure 12: Modifying the Style of Labels
 

The background of the second label is set to be fully transparent. The third label is set to have a purple background. Other types of changes are possible, such as changes to fonts and padding.

Changing All Components With Themes

Using style objects is fine for changing components individually, but if you'd like to change the appearance of all components in your application, you will need to use a theme.

A theme is a collection of properties, such as colors, fonts, and images. You can load a theme from a resource file and apply to update all the components in your application. Typically you would do this when you are intializing with code like this:

try {
  Resources r = Resources.open("/res/javaTheme.res");
  UIManager.getInstance().setThemeProps(r.getTheme("javaTheme"));
} catch (IOException ioe) {
  System.out.println("Couldn't load theme.");
}
 

Figure 13 and Figure 14 show two different themes that are frequently demonstrated with LWUIT.

 
Figure 13: The Star Theme
 
 
Figure 14: The Java Theme
 

LWUIT includes a desktop tool for editing and creating themes called ResourceEditor. You can use this tool to edit themes and view their general appearance in real time. The ResourceEditor is shown in Figure 15.

 
Figure 15: The LWUIT ResourceEditor Tool (Click on image to enlarge.)
 

For ultimate control of how components are drawn, you can create a custom look and feel that affects every aspect of component drawing. For more information, consult the API documentation for the LookAndFeel</> class.

Conclusion

This tutorial has shown you how to get started with LWUIT to create attractive application user interfaces for a variety of mobile platforms. LWUIT's basic set of components, flexible layouts, style and theming, animated screen transitions, and simple and useful event-handling mechanism provide many useful Swing-like features.

About the Author

Jonathan Knudsen is the author of several books and more than one hundred articles about Java technology and mobile robots. His most recent book is Kicking Butt With MIDP and MSA , published in 2008.

For More Information

Deep Dive Video: Ed Ort Interviews Yoav Barel of LWUIT Team
Java Platform, Micro Edition
LWUIT Home Page
Shai's Java and LWUIT Blog
Jonathan Knudsen's Web Site

Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
Your email address (no reply is possible without an address):
Sun Privacy Policy

Note: We are not able to respond to all submitted comments.