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的区别即第三种弹出式菜单。
评论