<!--
@page { size: 21cm 29.7cm; margin: 2cm }
P { margin-bottom: 0.21cm }
-->
MIDP程序有两种GUI的API,高级和低级。高级API提供了很多可视元素,而低级API则使得程序员可以进行象素级的操作。这两种API都是由基类Display派生的。
GUI种比较特别的一个可视元素就是菜单(Command)了。它是可视的,但并不派生于Display,而是直接派生自Object。菜单和高级API一样,其表现形式是由MIDP实现者定义的(不同平台的菜单模式不一样,不过通常都在左右下脚)。使用Command的好处是移植性好,编写简单。
不过显然Command也有其很不好的因素:太单调。就好像在windows上,只有少数早期的游戏会使用windows的对话框,按钮(曹操传等),稍微成熟一点的东西都会设计自己的菜单,以符合自己游戏的风格。在移动设备上,设备自定的菜单系统更加单调且不友好,那么自定义一个菜单就相对重要了。
菜单其实无外乎在屏幕上显示一页菜单画面,根据用户的不同选择进入不同的画面。当然,好的菜单应该根据需要设计多层多子菜单以突出主次,增加友好性。
给出一个简单的例子。该例子用List对象作为菜单,而把左右两个Command作为select和exit—移动设备上的程序应该随时提供立刻退出的功能。
主菜单类:
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Choice;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.List;
public class MainMenuScreen extends List implements CommandListener {
private Eliminator midlet;
private Command selectCommand = new Command("Select", Command.ITEM, 1);
private Command exitCommand = new Command("Exit", Command.EXIT, 1);
private Alert alert;
public MainMenuScreen(Eliminator midlet) {
super("Eliminator", Choice.IMPLICIT);
this.midlet = midlet;
append("New Game", null);
append("Settings", null);
append("High Scores", null);
append("Help", null);
append("About", null);
addCommand(exitCommand);
addCommand(selectCommand);
setCommandListener(this);
}
public MainMenuScreen(String arg0, int arg1, String[] arg2, Image[] arg3) {
super(arg0, arg1, arg2, arg3);
// TODO Auto-generated constructor stub
}
public void commandAction(Command c, Displayable d) {
if (c == exitCommand) {
midlet.mainMenuScreenQuit();
return;
} else if (c == selectCommand) {
processMenu();
return;
} else {
processMenu();
return;
}
}
private void processMenu() {
try {
List down = (List) midlet.display.getCurrent();
switch (down.getSelectedIndex()) {
case 0:
scnNewGame();
break;
case 1:
scnSettings();
break;
case 2:
scnHighScores();
break;
case 3:
scnHelp();
break;
case 4:
scnAbout();
break;
}
;
} catch (Exception ex) {
// Proper Error Handling should be done here
System.out.println("processMenu::" + ex);
}
}
private void scnNewGame() {
midlet.mainMenuScreenShow(null);
}
private void scnSettings() {
alert = new Alert("Settings", "Settings.......", null, null);
alert.setTimeout(Alert.FOREVER);
alert.setType(AlertType.INFO);
midlet.mainMenuScreenShow(alert);
}
private void scnHighScores() {
alert = new Alert("High Scores", "High Scores.......", null, null);
alert.setTimeout(Alert.FOREVER);
alert.setType(AlertType.INFO);
midlet.mainMenuScreenShow(alert);
}
private void scnHelp() {
alert = new Alert("Help", "Help....................", null, null);
alert.setTimeout(Alert.FOREVER);
alert.setType(AlertType.INFO);
midlet.mainMenuScreenShow(alert);
}
private void scnAbout() {
alert = new Alert("About", "Eliminator\nVersion 1.0.0\nby Jason Lam",
null, null);
alert.setTimeout(Alert.FOREVER);
alert.setType(AlertType.INFO);
midlet.mainMenuScreenShow(alert);
}
}
主MIDP类:
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Image;
import javax.microedition.midlet.MIDlet;
public class Eliminator extends MIDlet {
protected Display display;
private Image splashLogo;
private boolean isSplash = true;
MainMenuScreen mainMenuScreen;
public Eliminator() {
super();
// TODO Auto-generated constructor stub
}
public void startApp() {
display = Display.getDisplay(this);
mainMenuScreen = new MainMenuScreen(this);
if (isSplash) {
isSplash = false;
try {
splashLogo = Image.createImage("/splash.png");
new SplashScreen(display, mainMenuScreen, splashLogo, 3000);
} catch (Exception ex) {
mainMenuScreenShow(null);
}
} else {
mainMenuScreenShow(null);
}
}
protected void pauseApp() {
// TODO Auto-generated method stub
}
protected void destroyApp(boolean arg0) {
System.gc();
}
public Display getDisplay() {
return display;
}
private Image createImage(String filename) {
Image image = null;
try {
image = Image.createImage(filename);
} catch (Exception e) {
}
return image;
}
public void mainMenuScreenShow(Alert alert) {
if (alert == null)
display.setCurrent(mainMenuScreen);
else
display.setCurrent(alert, mainMenuScreen);
}
public void mainMenuScreenQuit() {
destroyApp(true);
}
}
MIDP中的mainMenuScreenShow(Alert
alert)方法是给主菜单对象用的,用以返回到主菜单。参数alert用来传递信息,通常作为返回主菜单的原因(如数据错误,没有最高分可以显示)。