User Interfaces in PersonalJava

In PersonalJava, we have available the power of JDK 1.1.8 AWT, except for some differences as noted in Section 5.2 of the PersonalJava 1.2 specification. Rather than include a tutorial on AWT, in this section we will construct some simple user interfaces and show how they appear on the PocketPC.

Frame

A Frame is the enclosing window of an application, and the basis of a simple user interface.

The application below shows a Frame being extended and created:

package com.javaonpdas.ui;

import java.awt.*;
import java.awt.event.*;

public class BasicWindow extends Frame {

  public BasicWindow(String title) {
    super(title);
    // handle frame closing events
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    } );
  }

  public static void main(String[] args) {
    Frame f = new BasicWindow("BasicWindow");
    f.setSize(f.getToolkit().getScreenSize());
    f.show();
  }
}

The screen shot in Figure 5.30 shows how this appears on the PocketPC.

Figure 5.30. BasicWindow

graphics/05fig30.jpg

Buttons

To add a button to a window, we use the addButton method on the Frame, as follows:

Button button1 = new Button("Button 1");
add(button1);
button1.addActionListener(this);

Creating three buttons in this way, and using a FlowLayout, we can create a simple application that writes to the console whenever a button is pressed.

package com.javaonpdas.ui;

import java.awt.*;
import java.awt.event.*;

public class Buttons extends Frame implements ActionListener {

  public Buttons(String title) {
    super(title);
    // handle frame closing events
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    } );
    // add components
    setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));
    Button button1 = new Button("Button 1");
    add(button1);
    button1.addActionListener(this);
    Button button2 = new Button("Button 2");
    add(button2);
    button2.addActionListener(this);
    Button button3 = new Button("Button 3");
    add(button3);
    button3.addActionListener(this);
  }

  public void actionPerformed(ActionEvent evt) {
    String cmd = evt.getActionCommand();
    System.out.println(cmd + " was pressed.");
  }

  public static void main(String[] args) {
    Frame f = new Buttons("Buttons");
    f.setSize(f.getToolkit().getScreenSize());
    f.show();
  }
}

The screen shot in Figure 5.31 shows how the application looks on the PocketPC.

Figure 5.31. Buttons

graphics/05fig31.gif

TextFields

A TextField is used for entering a single line of text. It is created with one of four constructors, as follows:

TextField textField1 = new TextField();
TextField textField2 = new TextField("Field 2");
TextField textField3 = new TextField("Field 3",20);
TextField textField4 = new TextField(20);

These text fields can be put together into an application, as follows:

package com.javaonpdas.ui;

import java.awt.*;
import java.awt.event.*;

public class TextFields extends Frame {

  public TextFields(String title) {
    super(title);
    // handle frame closing events
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    } );
    // add components
    setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));
    TextField textField1 = new TextField();
    TextField textField2 = new TextField("Field 2");
    TextField textField3 = new TextField("Field 3",20);
    TextField textField4 = new TextField(20);
    add(textField1);
    add(textField2);
    add(textField3);
    add(textField4);
  }

  public static void main(String[] args) {
    Frame f = new TextFields("TextFields");
    f.setSize(f.getToolkit().getScreenSize());
    f.show();
  }
}

Figure 5.32 shows how this appears on the PocketPC.

Figure 5.32. TextFields

graphics/05fig32.gif

Lists

Lists are used to display multiple items that can be selected. A List can be set so that a number of items can be displayed without scrolling, regardless of how many items are currently in the list. For example, the following code sets aside enough space for 10 items without scrolling, but it only puts seven items in the list for now:

List list = new List(10);
list.add("Item 1");
list.add("Item 2");
list.add("Item 3");
list.add("Item 4");
list.add("Item 5");
list.add("Item 6");
list.add("Item 7");

This code can be put into an application as follows:

package com.javaonpdas.ui;

import java.awt.*;
import java.awt.event.*;

public class Lists extends Frame {
  public Lists(String title) {
    super(title);
    // handle frame closing events
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    } );
    // add components
    setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));
    List list = new List(10);
    list.add("Item 1");
    list.add("Item 2");
    list.add("Item 3");
    list.add("Item 4");
    list.add("Item 5");
    list.add("Item 6");
    list.add("Item 7");
    add(list);
  }

  public static void main(String[] args) {
    Frame f = new Lists("Lists");
    f.setSize(f.getToolkit().getScreenSize());
    f.show();
  }
}

Figure 5.33 shows the screen shot.

Figure 5.33. Lists

graphics/05fig33.gif

Checkboxes

Checkboxes are used for making a choice of a small number of options, which may or may not be mutually exclusive. Checkboxes are created as follows:

Checkbox checkbox1 = new Checkbox("Box 1", null, true);
Checkbox checkbox2 = new Checkbox("Box 2", null, false);
Checkbox checkbox3 = new Checkbox("Box 3", null, false);
Checkbox checkbox4 = new Checkbox("Box 4", null, false);
Checkbox checkbox5 = new Checkbox("Box 5", null, false);

In this example, the checkboxes represent choices that are not mutually exclusive, and hence their group parameter is null. The first checkbox's state is set to true, and so it will be checked.

This code can be put into an application as follows:

package com.javaonpdas.ui;

import java.awt.*;
import java.awt.event.*;

public class Checkboxes extends Frame {

  public Checkboxes(String title) {
    super(title);
    // handle frame closing events
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    } );
    // add components
    setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));
    Checkbox checkbox1 = new Checkbox("Box 1", null, true);
    Checkbox checkbox2 = new Checkbox("Box 2", null, false);
    Checkbox checkbox3 = new Checkbox("Box 3", null, false);
    Checkbox checkbox4 = new Checkbox("Box 4", null, false);
    Checkbox checkbox5 = new Checkbox("Box 5", null, false);
    add(checkbox1);
    add(checkbox2);
    add(checkbox3);
    add(checkbox4);
    add(checkbox5);
  }

  public static void main(String[] args) {
    Frame f = new Checkboxes("Checkboxes");
    f.setSize(f.getToolkit().getScreenSize());
    f.show();
  }
}

Figure 5.34 shows the display on the PocketPC.

Figure 5.34. Checkboxes

graphics/05fig34.gif

FileDialog

The FileDialog uses the standard file choosing dialog for the platform, for the purpose of identifying a file to open or a directory in which to save a file. The dialog object can then be queried to find the file selected and the directory. The FileDialog is modal, so the application's main thread blocks while the dialog is displayed:

FileDialog dialog =
  new FileDialog(this, "Open a file", FileDialog.LOAD);
dialog.show();
textField.setText(dialog.getFile());

Putting this code fragment into an application:

package com.javaonpdas.ui;

import java.awt.*;
import java.awt.event.*;

public class FileDialogs extends Frame
  implements ActionListener {

  private TextField textField = null;

  public FileDialogs(String title) {
    super(title);
    // handle frame closing events
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    } );
    // add components
    setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));
    Button button = new Button("Open");
    add(button);
    textField = new TextField(20);
    add(textField);
    button.addActionListener(this);
  }

  public void actionPerformed(ActionEvent evt) {
    FileDialog dialog = new FileDialog(this, "Open a file",
      FileDialog.LOAD);
    dialog.show();
    textField.setText(dialog.getFile());
  }

  public static void main(String[] args) {
    Frame f = new FileDialogs("FileDialogs");
    f.setSize(f.getToolkit().getScreenSize());
    f.show();
  }
}

And displaying the application on the PocketPC, we have the application window shown in Figure 5.35.

Figure 5.35. FileDialogs

graphics/05fig35.gif

Pressing the Open button, the FileDialog is displayed as shown in Figure 5.36.

Figure 5.36. Open file dialog

graphics/05fig36.gif

On selecting the Buttons.lnk file, the FileDialog closes and the selected filename is displayed in the text field, as shown in Figure 5.37.

Figure 5.37. The selected file name

graphics/05fig37.gif

Layouts

PersonalJava supports the full set of AWT layouts.

BorderLayout

The BorderLayout is used when the screen components are arranged along edges of the window. The following code for a simple application shows the BorderLayout used to arrange buttons on the main window (Figure 5.38).

package com.javaonpdas.ui;

import java.awt.*;
import java.awt.event.*;

public class BorderLayoutWindow extends Frame {

  public BorderLayoutWindow(String title) {
    super(title);
    // handle frame closing events
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    } );
    // add components
    setLayout(new BorderLayout());
    add("North",  new Button("North"));
    add("South",  new Button("South"));
    add("East",   new Button("East"));
    add("West",   new Button("West"));
    add("Center", new Button("Center"));
  }

  public static void main(String[] args) {
    Frame f = new BorderLayoutWindow("BorderLayoutWindow");
    f.setSize(f.getToolkit().getScreenSize());
    f.show();
  }
}
Figure 5.38. BorderLayoutWindow

graphics/05fig38.gif

CardLayout

The CardLayout is used to display a series of screens, one at a time. The result is a component that acts as a stack of cards.

To demonstrate the CardLayout on the PocketPC, we can use the application CardTest.java, which is included in the JDK 1.1.8 demo directory. The main window is shown in Figure 5.39. Only one modification was necessary to make it work. In the main() method, rather than

f.setSize(300, 300);
Figure 5.39. CardTest

graphics/05fig39.gif

it works better on the PocketPC if we set the frame's size to be the screen size, as follows:

f.setSize(f.getToolkit().getScreenSize());
FlowLayout

The FlowLayout is used to display screen components on a line in a left-to-right flow, with the components being centered on the line, as shown in Figure 5.40.

package com.javaonpdas.ui;

import java.awt.*;
import java.awt.event.*;

public class FlowLayoutWindow extends Frame {
  public FlowLayoutWindow(String title) {
    super(title);
    // handle frame closing events
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    } );
    // add components
    setLayout(new FlowLayout());
    Button button1 = new Button("Ok");
    Button button2 = new Button("Open");
    Button button3 = new Button("Close");
    add(button1);
    add(button2);
    add(button3);
  }

  public static void main(String[] args) {
    Frame f = new FlowLayoutWindow("FlowLayoutWindow");
    f.setSize(f.getToolkit().getScreenSize());
    f.show();
  }
}
Figure 5.40. FlowLayoutWindow

graphics/05fig40.gif

GridBagLayout

The GridBagLayout is used to display components in a dynamic grid, where the components do not need to be of equal size, as shown in Figure 5.41.

package com.javaonpdas.ui;

import java.awt.*;
import java.awt.event.*;

public class GridBagLayoutWindow extends Frame {

  protected void makebutton(String name,
                            GridBagLayout gridbag,
                            GridBagConstraints c) {
    Button button = new Button(name);
    gridbag.setConstraints(button, c);
    add(button);
  }

  public GridBagLayoutWindow(String title) {
    super(title);
    // handle frame closing events
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    } );
    // add components
    GridBagLayout gridbag = new GridBagLayout();
    GridBagConstraints c = new GridBagConstraints();
    setFont(new Font("Helvetica", Font.PLAIN, 14));
    setLayout(gridbag);
    c.fill = GridBagConstraints.BOTH;
    c.weightx = 1.0;
    makebutton("Button1", gridbag, c);
    makebutton("Button2", gridbag, c);
    makebutton("Button3", gridbag, c);
    c.gridwidth = GridBagConstraints.REMAINDER;
    makebutton("Button4", gridbag, c);
    c.weightx = 0.0;
    makebutton("Button5", gridbag, c);
    c.gridwidth = GridBagConstraints.RELATIVE;
    makebutton("Button6", gridbag, c);
    c.gridwidth = GridBagConstraints.REMAINDER;
    makebutton("Button7", gridbag, c);
    c.gridwidth = 1;
    c.gridheight = 2;
    c.weighty = 1.0;
    makebutton("Button8", gridbag, c);
    c.weighty = 0.0;
    c.gridwidth = GridBagConstraints.REMAINDER;
    c.gridheight = 1;
    makebutton("Button9", gridbag, c);
    makebutton("Button10", gridbag, c);
  }

  public static void main(String[] args) {
    Frame f = new GridBagLayoutWindow("GridBagLayoutWindow");
    f.pack();
    f.setSize(f.getPreferredSize());
    f.show();
  }
}
Figure 5.41. GridBagLayoutWindow

graphics/05fig41.gif

GridLayout

The GridLayout is used to display screen components in a rectangular grid, where each component is of equal size, as shown in Figure 5.42.

package com.javaonpdas.ui;

import java.awt.*;
import java.awt.event.*;

public class GridLayoutWindow extends Frame {

  public GridLayoutWindow(String title) {
    super(title);
    // handle frame closing events
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    } );
    // add components
    setLayout(new GridLayout(3,2));
    add(new Button("1"));
    add(new Button("2"));
    add(new Button("3"));
    add(new Button("4"));
    add(new Button("5"));
    add(new Button("6"));
  }
  public static void main(String[] args) {
    Frame f = new GridLayoutWindow("GridLayoutWindow");
    f.pack();
    f.setSize(f.getToolkit().getScreenSize());
    f.show();
  }
}
Figure 5.42. GridLayoutWindow

graphics/05fig42.gif

Menus

Menus are a common way of organizing command selections in an application. The MenuWindow application demonstrates how menus appear on the PocketPC. A drop-down menu is shown in Figure 5.43.

package com.javaonpdas.ui;

import java.awt.*;
import java.awt.event.*;

public class MenuWindow extends Frame {

  public MenuWindow(String title) {
    super(title);
    // handle frame closing events
    addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    } );
    // add components
    MenuBar menuBar = new MenuBar();
    setMenuBar(menuBar);
    Menu menu1 = new Menu("Menu 1");
    Menu menu2 = new Menu("Menu 2");
    Menu menu3 = new Menu("Menu 3");
    menuBar.add(menu1);
    menuBar.add(menu2);
    menuBar.add(menu3);
    MenuItem item11 = new MenuItem("Item 1.1");
    MenuItem item12 = new MenuItem("Item 1.2");
    MenuItem item21 = new MenuItem("Item 2.1");
    MenuItem item22 = new MenuItem("Item 2.2");
    MenuItem item31 = new MenuItem("Item 3.1");
    MenuItem item32 = new MenuItem("Item 3.2");
    menu1.add(item11);
    menu1.add(item12);
    menu2.add(item21);
    menu2.add(item22);
    menu3.add(item31);
    menu3.add(item32);
  }

  public static void main(String[] args) {
    Frame f = new MenuWindow("MenuWindow");
    f.setSize(f.getToolkit().getScreenSize());
    f.show();
  }
}
Figure 5.43. MenuWindow

graphics/05fig43.gif