站内搜索: 请输入搜索关键词
当前页面: 图书首页 > Wireless Java Developing with J2ME, Second Edition

An Example - Wireless Java Developing with J2ME, Second Edition

Previous Section Next Section

An Example

In this section, I'll show you StationSign, a CustomItem of medium complexity. StationSign has the following features:

  • Implements a simple scrolling list of string choices. Pointer events and key events cause the current selection to move to the next choice. The scrolling is animated. StationSign is a Runnable—a separate thread is created in the constructor and used to call the run() method. If there's a difference between the current display state of the item and the current selection, run() reconciles the two by scrolling.

  • Conforms to the device's look and feel by using the font for static text and colors returned from Display's getColor() method.

  • Does not implement internal traversal.

  • Uses the traverse() and traverseOut() methods to recognize focus and paint using highlight colors. When traverse() is called, StationSign sets a boolean member variable, mFocus, to indicate that the item has focus. In the paint() method, mFocus is used to determine what colors are used to draw the item. When traverseOut() is called, mFocus is set to false indicating that focus has been lost.

The entire source code for StationSign is shown in Listing 7-3.

Listing 7-3: The StationSign Custom Item
Start example
import java.util.Vector;

import javax.microedition.lcdui.*;

public class StationSign
    extends CustomItem
    implements Runnable {
  private Vector mValues;
  private int mSelection;
  private boolean mTrucking;

  private Display mDisplay;
  private Font mFont;
  private int mVisibleIndexTimesTen;
  private boolean mFocus;

  public StationSign(String title, Display display) {
    super(title);
    mDisplay = display;
    mValues = new Vector();
    mSelection = 0;
    mTrucking = true;
    mFont = Font.getFont(Font.FONT_STATIC_TEXT);
    mVisibleIndexTimesTen = mSelection * 10;

    Thread t = new Thread(this);
    t.start();
  }

  public void add(String value) {
    if (value == null) return;
    mValues.addElement(value);
  }

  public void remove(String value) {
    if (value == null) return;
    mValues.removeElement(value);
  }

  public String getSelection() {
    if (mValues.size() == 0) return "";
    return (String)mValues.elementAt(mSelection);
  }

  public void flip() {
    mSelection++;
    if (mSelection >= mValues.size()) mSelection = 0;
  }

  public void dispose() {
    mTrucking = false;
  }

  // Runnable interface.

  public void run() {
    while (mTrucking) {
      int target = mSelection * 10;
      if (mVisibleIndexTimesTen != target) {
        mVisibleIndexTimesTen++;
        if (mVisibleIndexTimesTen >= mValues.size() * 10)
          mVisibleIndexTimesTen = 0;
        repaint();
      }
      try { Thread.sleep(50); }
      catch (InterruptedException ie) {}
    }
  }

  // CustomItem abstract methods.

  public int getMinContentWidth() {
    // Loop through the values. Find the maximum width.
    int maxWidth = 0;
    for (int i = 0; i < mValues.size(); i++) {
      String value = (String)mValues.elementAt(i);
      int width = mFont.stringWidth(value);
      maxWidth = Math.max(maxWidth, width);
    }
    // Don't forget about the title, although we don't
    // really know what font is used for that.
    int width = mFont.stringWidth(getLabel()) + 20;
    maxWidth = Math.max(maxWidth, width);
    return maxWidth;
  }
  public int getMinContentHeight() {
    return mFont.getHeight();
  }

  public int getPrefContentWidth(int width) {
    return getMinContentWidth();
  }

  public int getPrefContentHeight(int height) {
    return getMinContentHeight();
  }

  public void paint(Graphics g, int w, int h) {
    int fraction = mVisibleIndexTimesTen % 10;
    int visibleIndex = (mVisibleIndexTimesTen - fraction) / 10;
    String value = (String)mValues.elementAt(visibleIndex);

    g.setFont(mFont);
    int bc = mDisplay.getColor(Display.COLOR_BACKGROUND);
    int fc = mDisplay.getColor(Display.COLOR_FOREGROUND);
    if (mFocus == true) {
      bc = mDisplay.getColor(Display.COLOR_HIGHLIGHTED_BACKGROUND);
      fc = mDisplay.getColor(Display.COLOR_HIGHLIGHTED_FOREGROUND);
    }
    g.setColor(bc);
    g.fillRect(0, 0, w, h);
    g.setColor(fc);

    // Simple case: visibleIndex is aligned on a single item.
    if (fraction == 0) {
      g.drawString(value, 0, 0, Graphics.TOP | Graphics.LEFT);
      return;
    }

    // Complicated case: show two items and a line.
    int lineHeight = mFont.getHeight();
    int divider = lineHeight - lineHeight * fraction / 10;

    // Draw the piece of the visible value.
    g.drawString(value, 0, divider - lineHeight,
        Graphics.TOP | Graphics.LEFT);
    // Now get the next value.
    visibleIndex = (visibleIndex + 1) % mValues.size();
    value = (String)mValues.elementAt(visibleIndex);
    // Draw the line.
    g.setStrokeStyle(Graphics.DOTTED);
    g.drawLine(0, divider, w, divider);

    g.drawString(value, 0, divider,
        Graphics.TOP | Graphics.LEFT);
  }

  // CustomItem methods.

  protected void keyPressed(int keyCode) { flip (); }

  protected void pointerPressed(int x, int y) { flip(); }

  protected boolean traverse(int dir,
      int viewportWidth, int viewportHeight,
      int[] visRect_inout) {
    mFocus = true;
    repaint();
    return false;
  }

  protected void traverseOut() {
    mFocus = false;
    repaint();
  }
}
End example

The MIDlet in Listing 7-4 displays a form that contains a StationSign.

Listing 7-4: A MIDlet That Demonstrates StationSign
Start example
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class StationSignMIDlet
    extends MIDlet
    implements CommandListener {
  public void startApp() {
    Display display = Display.getDisplay(this);
    Form form = new Form("StationSignMIDlet");
    form.append(new StringItem("StringItem: ", "item one"));
    StationSign ss = new StationSign("Destination", display);
    ss.add("Albuquerque");
    ss.add("Savannah");
    ss.add("Pocatello");
    ss.add("Des Moines");
    form.append(ss);
    form.append(new StringItem("StringItem: ", "item two"));

    Command c = new Command("Exit", Command.EXIT, 0);
    form.addCommand(c);
    form.setCommandListener(this);

    display.setCurrent(form);
  }

  public void pauseApp() {}

  public void destroyApp(boolean unconditional) {}

  public void commandAction(Command c, Displayable s) {
    if (c.getCommandType() == Command.EXIT)
      notifyDestroyed();
  }
}
End example

The MIDlet in action appears in Figure 7-4. The figure shows an instance of StationSign sandwiched between two StringItems. You can navigate through the form to see how the appearance of StationSign changes when it has input focus. If you press the select key on StationSign, you'll see the next choice scroll into view.


Figure 7-4: StationSign in action in a Form

Previous Section Next Section