3.6.2 ImageItem 下面我们来看ImageItem,ImageItem和StringItem其实区别仅仅在于一个是显示图像,一个是文字,它同样有两个构造函数,其中用到最多的是5个参数的构造函数,第一个是该Item的Label,第二个是图片,第三个是等效线,第四个是取代的文字(图片无法现实时),第五个是外观(和StringItem相同)。 import javax.microedition.lcdui.*; import javax.microedition.midlet.*; public class ImageItemMIDlet extends MIDlet implements ItemCommandListener { private Display display; public ImageItemMIDlet() { display = Display.getDisplay(this); } public void startApp() { Image img = null ; try { img = Image.createImage("/pic.png") ; }catch(Exception e){} Form f = new Form("ImageItem测试") ; f.append(img) ; ImageItem ii1 = new ImageItem("图片1",img, Item.LAYOUT_CENTER|Item.LAYOUT_NEWLINE_BEFORE,"图片1取代文字",Item.BUTTON); f.append(ii1) ; ImageItem ii2 = new ImageItem("图片2",img, Item.LAYOUT_RIGHT|Item.LAYOUT_NEWLINE_BEFORE,"图片2取代文字",Item.HYPERLINK); f.append(ii2) ; display.setCurrent(f); } public void commandAction(Command c,Item i) { System.out.println(c.getLabel()); System.out.println(i.getLabel()); } public void pauseApp() { } public void destroyApp(boolean unconditional) { } } 3.7 CustomItem CustomItem是Item中一个比较重要的子类,它最大的优点是提高了Form中的可交互性。它和Canvas有很大的相似处。我们通过改写CustomItem可以实现完全控制在新的子类中条目区域的显示,它可以定义使用的颜色,字体和图形,包括特殊高亮的条目可能有的所有的焦点状态,只有条目的Label是有系统控制生成的,但是Label总是生成在CustomItem的内容区域外。 每个CustomItem都负责把它的行为与目标设备上可用的交互模式匹配。一个CustomItem调用方法来观察特定设备所支持的交互模式,这个方法会返回一个支持模式的位标记,支持的模式会的返回对应位会被设置,不支持的不被设置。 CustomItem一个比较重要的特性即是Form内部的遍历,即实现可能临时把遍历的责任委派给Item本身,这样可以实现特殊的高亮,动画等等效果。 由于customItem在Form类里扮演很重要的角色,其内容很庞杂,我们通过三个代码段来教读者如何使用CustomItem,希望大家通过对代码的深刻认识,提高自己对CustomItem的掌握程度。 import javax.microedition.lcdui.*; import javax.microedition.midlet.MIDlet; public class CustomItemDemo extends MIDlet implements CommandListener { private final static Command CMD_EXIT = new Command("Exit", Command.EXIT, 1); private Display display; private boolean firstTime; private Form mainForm; public CustomItemDemo() { firstTime = true; mainForm = new Form("Custom Item"); } protected void startApp() { if(firstTime) { display = Display.getDisplay(this); mainForm.append(new TextField("Upper Item", null, 10, 0)); mainForm.append(new Table("Table", Display.getDisplay(this))); mainForm.append(new TextField("Lower Item", null, 10, 0)); mainForm.addCommand(CMD_EXIT); mainForm.setCommandListener(this); firstTime = false; } display.setCurrent(mainForm); } public void commandAction(Command c, Displayable d) { if (c == CMD_EXIT) { destroyApp(false); notifyDestroyed(); } } protected void destroyApp(boolean unconditional) { } protected void pauseApp() { } } import javax.microedition.lcdui.*; public class Table extends CustomItem implements ItemCommandListener { private final static Command CMD_EDIT = new Command("Edit", Command.ITEM, 1); private Display display; private int rows = 5; private int cols = 3; private int dx = 50; private int dy = 20; private final static int UPPER = 0; private final static int IN = 1; private final static int LOWER = 2; private int location = UPPER; private int currentX = 0; private int currentY = 0; private String[][] data = new String[rows][cols]; // Traversal stuff //indicating support of horizontal traversal internal to the CustomItem boolean horz; //indicating support for vertical traversal internal to the CustomItem. boolean vert; public Table(String title, Display d) { super(title); display = d; setDefaultCommand(CMD_EDIT); setItemCommandListener(this); int interactionMode = getInteractionModes(); horz = ((interactionMode & CustomItem.TRAVERSE_HORIZONTAL) != 0); vert = ((interactionMode & CustomItem.TRAVERSE_VERTICAL) != 0); } protected int getMinContentHeight() { return (rows * dy) + 1; } protected int getMinContentWidth() { return (cols * dx) + 1; } protected int getPrefContentHeight(int width) { return (rows * dy) + 1; } protected int getPrefContentWidth(int height) { return (cols * dx) + 1; } protected void paint(Graphics g, int w, int h) { for (int i = 0; i <= rows; i++) { g.drawLine(0, i * dy, cols * dx, i * dy); } for (int i = 0; i <= cols; i++) { g.drawLine(i * dx, 0, i * dx, rows * dy); } int oldColor = g.getColor(); g.setColor(0x00D0D0D0); g.fillRect((currentX * dx) + 1, (currentY * dy) + 1, dx - 1, dy - 1); g.setColor(oldColor); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { if (data[i][j] != null) { // store clipping properties int oldClipX = g.getClipX(); int oldClipY = g.getClipY(); int oldClipWidth = g.getClipWidth(); int oldClipHeight = g.getClipHeight(); g.setClip((j * dx) + 1, i * dy, dx - 1, dy - 1); g.drawString(data[i][j], (j * dx) + 2, ((i + 1) * dy) - 2, Graphics.BOTTOM | Graphics.LEFT); // restore clipping properties g.setClip(oldClipX, oldClipY, oldClipWidth, oldClipHeight); } } } } protected boolean traverse(int dir, int viewportWidth, int viewportHeight, int[] visRect_inout) { if (horz && vert) { switch (dir) { case Canvas.DOWN: if (location == UPPER) { location = IN; } else { if (currentY < (rows - 1)) { currentY++; repaint(currentX * dx, (currentY - 1) * dy, dx, dy); repaint(currentX * dx, currentY * dy, dx, dy); } else { location = LOWER; return false; } } break; case Canvas.UP: if (location == LOWER) { location = IN; } else { if (currentY > 0) { currentY--; repaint(currentX * dx, (currentY + 1) * dy, dx, dy); repaint(currentX * dx, currentY * dy, dx, dy); } else { location = UPPER; return false; } } break; case Canvas.LEFT: if (currentX > 0) { currentX--; repaint((currentX + 1) * dx, currentY * dy, dx, dy); repaint(currentX * dx, currentY * dy, dx, dy); } break; case Canvas.RIGHT: if (currentX < (cols - 1)) { currentX++; repaint((currentX - 1) * dx, currentY * dy, dx, dy); repaint(currentX * dx, currentY * dy, dx, dy); } } } else if (horz || vert) { switch (dir) { case Canvas.UP: case Canvas.LEFT: if (location == LOWER) { location = IN; } else { if (currentX > 0) { currentX--; repaint((currentX + 1) * dx, currentY * dy, dx, dy); repaint(currentX * dx, currentY * dy, dx, dy); } else if (currentY > 0) { currentY--; repaint(currentX * dx, (currentY + 1) * dy, dx, dy); currentX = cols - 1; repaint(currentX * dx, currentY * dy, dx, dy); } else { location = UPPER; return false; } } break; case Canvas.DOWN: case Canvas.RIGHT: if (location == UPPER) { location = IN; } else { if (currentX < (cols - 1)) { currentX++; repaint((currentX - 1) * dx, currentY * dy, dx, dy); repaint(currentX * dx, currentY * dy, dx, dy); } else if (currentY < (rows - 1)) { currentY++; repaint(currentX * dx, (currentY - 1) * dy, dx, dy); currentX = 0; repaint(currentX * dx, currentY * dy, dx, dy); } else { location = LOWER; return false; } } } } else { //In case of no Traversal at all: (horz|vert) == 0 } visRect_inout[0] = currentX; visRect_inout[1] = currentY; visRect_inout[2] = dx; visRect_inout[3] = dy; return true; } public void setText(String text) { data[currentY][currentX] = text; repaint(currentY * dx, currentX * dy, dx, dy); } public void commandAction(Command c, Item i) { if (c == CMD_EDIT) { TextInput textInput = new TextInput(data[currentY][currentX], this, display); display.setCurrent(textInput); } } } import javax.microedition.lcdui.*; import javax.microedition.midlet.MIDlet; public class TextInput extends TextBox implements CommandListener { private final static Command CMD_OK = new Command("OK", Command.OK, 1); private final static Command CMD_CANCEL = new Command("Cancel", Command.CANCEL, 1); private Table parent; private Display display; public TextInput(String text, Table parent, Display display) { super("Enter Text", text, 50, TextField.ANY); this.parent = parent; this.display = display; addCommand(CMD_OK); addCommand(CMD_CANCEL); setCommandListener(this); } public void commandAction(Command c, Displayable d) { if (c == CMD_OK) { // update the table's cell and return parent.setText(getString()); display.setCurrentItem(parent); } else if (c == CMD_CANCEL) { // return without updating the table's cell display.setCurrentItem(parent); } } } 3.8 TextField和DateField TextField和我们前面讲的TextBox大同小异,只是它是作为Form的一个子类存在,而TextBox则是和Form平起平坐,因此我们直接给出代码方便大家的学习。 import javax.microedition.lcdui.*; import javax.microedition.midlet.*; public class TextFieldWithItemStateListenerMIDlet extends MIDlet implements ItemStateListener { private Display display; public TextFieldWithItemStateListenerMIDlet() { display = Display.getDisplay(this); } TextField name ; TextField tel ; TextField summary ; public void startApp() { Form f = new Form("TextField测试") ; name = new TextField("姓名","",8,TextField.ANY) ; tel = new TextField("电话","",14,TextField.PHONENUMBER) ; summary = new TextField("总结","",30,TextField.UNEDITABLE) ; f.append(name) ; f.append(tel) ; f.append(summary) ; f.setItemStateListener(this); display.setCurrent(f); } public void itemStateChanged(Item item) { if(item==name) { summary.setString("输入的姓名为:"+name.getString()); }else if(item==tel) { summary.setString("输入的电话为:"+tel.getString()); }else { summary.setString(""); } } public void pauseApp() { } public void destroyApp(boolean unconditional) { } } DateField的目的是方便用户输入时间,它的构造函数共有三个参数,一个是Label,一个是输入模式,一个是java.util.TimeZone对象,也可以省去第三个参数,只使用前两个。 3.9 Gauge和Spacer,ChoiceGroup 3.9.1 Gauge Alert有一套方法可以显示进度,利用setIndicator()/getIndicator()这组函数,可以显示进度的画面。Gauge的最大用处就是拿来当进度显示使用。 拿来当进度显示用的Gauge对象必须满足如下要求: l 控制与用户交互的构造函数的第二个参数必须为flase l 不能被其他的Form或者Alert使用 l 不能加入Command l 不能有Label l 不能自己设定等效线的位置。 l 不能自己设定组件的大小。 大家可以参考如下的代码: import javax.microedition.lcdui.*; import javax.microedition.midlet.*; public class AlertWithIndicatorMIDlet extends MIDlet implements CommandListener { private Display display; public AlertWithIndicatorMIDlet() { display = Display.getDisplay(this); } Gauge g ; public void startApp() { Alert al = new Alert("处理中"); al.setType(AlertType.INFO); al.setTimeout(Alert.FOREVER); al.setString("系统正在处理中"); g = new Gauge(null,false,10,0) ; al.setIndicator(g); Command start = new Command("开始",Command.OK,1) ; Command stop = new Command("停止",Command.STOP,1) ; al.addCommand(start); al.addCommand(stop); al.setCommandListener(this); display.setCurrent(al); } public void commandAction(Command c,Displayable s) { String cmd = c.getLabel() ; if(cmd.equals("开始")) { for(int i=0 ; i <11 ; i++) { g.setValue(i); try { Thread.sleep(500); }catch(Exception e){} } }else if(cmd.equals("停止")) { notifyDestroyed() ; } } public void pauseApp() { } public void destroyApp(boolean unconditional) { } } 3.9.2 Spacer Spacer的用处很简单,就是加一处空白,大家可以参考API文档进行实际开发。 3.9.3 ChoiceGroup ChoiceGroup和List大同小异,因为二者都实现了Choice接口,所以在很多地方是一样的,但是请注意一点,在这里我们不能使用Choice.IMPLICIT类型,只能用Choice.EXCLUSIVE,Choice.MUTIPLE,Choice.POPUP,三种类型,与List的区别即第三种弹出式菜单。

评论