这个案例描述了如何使用低级UI API,也就是Canvas来创建高级菜单
本案例共包括三个类,MIDlet,GUI和Menu。其中,当MIDlet启动后,Options和exit会绘制在屏幕
的底部,当用户按左或者右软键的时候,程序会根据键值响应不同的动作。例如选择options后,
会弹出menu供用户选择。
GUI类持有一个Menu对象,并且根据用户的输入来改变Menu的状态,然后重新绘制屏幕。事实上menu只有两种状态,一种是激活的,一种是非
激活的。只有激活状态下,菜单才会显示出来,并且可以接受用户的上下左右选择,当用户选择了Menu里面的选项之后,GUI会把用户的选择显示在屏幕上。
代码如下所示:
//Midlet.java
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class Midlet extends MIDlet {
private Display display;
private GUI gui;
public void startApp() {
display = Display.getDisplay(this);
if (display == null) {
destroyApp(false);
} // end if display is not allocated
gui = new GUI(this);
display.setCurrent(gui);
gui.start();
} // end startApp
public void pauseApp() {
} // end pauseApp
public void destroyApp(boolean unconditional) {
display.setCurrent(null);
notifyDestroyed();
} // end destroyApp
} // end Midlet.java
//GUI.java
import java.util.*;
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;
import java.io.*;
import javax.microedition.io.*;
import javax.microedition.io.file.*;
class GUI extends GameCanvas {
private Midlet midlet;
private Display display;
private Graphics g;
private Font font;
private int width = 0;
private int height = 0;
private Menu menu;
private String leftOption;
private String rightOption;
private String[] menuOptions;
private int currentlySelectedIndex = 0;
private boolean menuIsActive = false;
/**
* Creates a new instance of GUI.
*/
public GUI(Midlet midlet) {
super(false);
this.midlet = midlet;
font = Font.getFont(Font.FACE_SYSTEM,
Font.STYLE_PLAIN, Font.SIZE_SMALL);
setFullScreenMode(true);
width = getWidth();
height = getHeight();
g = getGraphics();
leftOption = "Options";
// will be displayed only when menu is not active
rightOption = "Exit";
// will be displayed only when menu is not active
menuOptions = new String[] {"Option #1", "Option #2", "Option #3",
"Option #4"};
menu = new Menu(leftOption, rightOption, menuOptions);
} // end constructor
public void start() {
clearScreen();
menu.drawInactiveMenu(this, g);
} // end start
// softkey codes may vary from phone to phone
// -6 and -7 values are OK on Nokia phones
private int LEFT_SOFTKEY_CODE = -6;
// check it for your phone model
private int RIGHT_SOFTKEY_CODE = -7;
// check it for your phone model
protected void keyPressed(int keyCode) {
// work with menu according to its current state
if (menuIsActive) { // draw active menu
if (keyCode == RIGHT_SOFTKEY_CODE) {
// draw inactive menu again
clearScreen();
menu.drawInactiveMenu(this, g);
menuIsActive = false;
} // end if "Cancel" was pressed on active menu
// otherwise check navigation
keyCode = getGameAction(keyCode);
if (keyCode == UP) {
currentlySelectedIndex--;
if (currentlySelectedIndex < 0) {
currentlySelectedIndex = 0; // stay within limits
}
clearScreen();
menu.drawActiveMenu(this, g, currentlySelectedIndex);
// repaint active menu
} else if (keyCode == DOWN) { // end if UP button was pressed
currentlySelectedIndex++;
if (currentlySelectedIndex >= menuOptions.length) {
currentlySelectedIndex = menuOptions.length - 1;
// stay within limits
}
clearScreen();
menu.drawActiveMenu(this, g, currentlySelectedIndex);
// repaint active menu
} else if (keyCode == FIRE) { // end if DOWN button was pressed
// menu option is selected
// simply draw selected option
clearScreen();
g.setColor(0x000000); // black
g.drawString("[" +
menuOptions[currentlySelectedIndex] +
"] was selected", 10, 15, g.LEFT | g.TOP);
menu.drawInactiveMenu(this, g);
menuIsActive = false;
} // end if FIRE button was pressed
} else { // end if menu is active, draw inactive menu
// check if the "Options" or "Exit" buttons were pressed
if (keyCode == LEFT_SOFTKEY_CODE) { // "Options" pressed
clearScreen();
currentlySelectedIndex = 0;
menu.drawActiveMenu(this, g, currentlySelectedIndex);
// activate menu
menuIsActive = true;
} else if (keyCode == RIGHT_SOFTKEY_CODE) { // end if "Options" was pressed
exitGUI();
} // end if "Exit" was pressed
} // end if menu is not active
} // end keyPressed
public void exitGUI() {
midlet.destroyApp(false);
midlet.notifyDestroyed();
} // end exitGUI
public void clearScreen() {
g.setColor(0xffffff); // white
g.fillRect(0, 0, width, height);
flushGraphics();
} // end clearScreen
} // end GUI.java
//Menu.java
import java.util.*;
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
public class Menu {
private String leftOption;
// will be displayed when menu is inactive
private String rightOption;
// will be displayed when menu is inactive
private String cancelOption = "Cancel";
// also may be "Back" or something else
private String[] menuOptions;
private int padding = 5; // just like in CSS
/**
* Creates a new instance of Menu.
*/
public Menu(String leftOption, String rightOption, String[]
menuOptions) {
this.leftOption = leftOption;
this.rightOption = rightOption;
this.menuOptions = menuOptions;
} // end constructor
public void drawInactiveMenu(GameCanvas canvas, Graphics g) {
// create inactive menu font
Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD,
Font.SIZE_MEDIUM);
int fontHeight = font.getHeight();
// clear inactive menu background
int width = canvas.getWidth();
int height = canvas.getHeight();
g.setColor(0xcccccc); // grey color
g.fillRect(0, height - fontHeight - 2 * padding, width, height);
// draw left and right menu options
g.setFont(font);
g.setColor(0x000000); // black
g.drawString(leftOption, padding, height - padding,
g.LEFT | g.BOTTOM);
g.drawString(rightOption, width - padding, height - padding,
g.RIGHT | g.BOTTOM);
canvas.flushGraphics();
} // end drawInactiveMenu
public void drawActiveMenu(GameCanvas canvas,
Graphics g, int selectedOptionIndex) {
// create active menu font
Font font = Font.getFont(Font.FACE_SYSTEM,
Font.STYLE_BOLD, Font.SIZE_MEDIUM);
int fontHeight = font.getHeight();
// clear menu bar background
int width = canvas.getWidth();
int height = canvas.getHeight();
g.setColor(0xcccccc);
g.fillRect(0, height - fontHeight - 2 * padding,
width, height);
// draw default menu bar options
g.setFont(font);
g.setColor(0x000000); // black
// draw "Cancel" option
g.drawString(cancelOption, width - padding, height - padding,
g.RIGHT | g.BOTTOM);
canvas.flushGraphics();
// draw menu options
if (menuOptions != null) {
// check out the max width of a menu
// (for the specified menu font)
int menuMaxWidth = 0;
int menuMaxHeight = 0;
int currentWidth = 0;
// we'll simply check each option and find the
// maximal width
for (int i = 0; i < menuOptions.length; i++) {
currentWidth = font.stringWidth(menuOptions[i]);
if (currentWidth > menuMaxWidth) {
menuMaxWidth = currentWidth; // update
}
menuMaxHeight += fontHeight + padding;
// for a current menu option
} // end for each menu option
menuMaxWidth += 2 * padding;
// padding from left and right
// now we know the bounds of active menu
// draw active menu's background
g.setColor(0xcccccc);
g.fillRect(0, // x
height - fontHeight -
2 * padding - menuMaxHeight, // y
menuMaxWidth,
menuMaxHeight);
// draw menu options (from up to bottom)
g.setFont(font);
int menuOptionX = padding;
int menuOptionY = height - fontHeight - 2 * padding
- menuMaxHeight + padding;
for (int i = 0; i < menuOptions.length; i++) {
if (i != selectedOptionIndex) {
// draw unselected menu option
g.setColor(0x000000); // black
} else {
// end if draw unselected menu option, draw selected="selected" menu option
g.setColor(0x0000ff); // blue
} // end if draw selected="selected" menu option
g.drawString(menuOptions[i], menuOptionX,
menuOptionY, g.LEFT | g.TOP);
menuOptionY += padding + fontHeight;
} // end for each menu option
canvas.flushGraphics();
} // end if menu options were specified
} // end drawActiveMenu
} // end Menu.java