J2ME做界面开发时,高级界面是无法自定义接受按键响应的(如Form只能接收左右软键,而List则接收左右软键, Fire键),而只有低级界面(如Canvas, GameCanvas, CustomItem)才可以自定义按键接收(重写keyPressed, keyReleased等函数). 而在实际开发中,所有按键响应的发起都得由左右软键开始,比如选择, 退出等命令,一般情况下,这是足够的.然而界面不够友好,用惯了电脑软件的用户更倾向于直接点击某个命令按钮(即Button)来发起一个事件,很可惜的是J2ME中并没有button的概念.
这篇文章的目的就是使高级界面可以接收Fire按键响应:
1. 所有注册的Item都可以接收Fire按键响应,并执行特定动作
2. 每个Item只能绑定一个Fire按键响应
在这里,利用了Polish的UIAccess软件包(主要用于操控UI),并将Fire按键响应映射到命令Command上,实现了接收Fire按键响应.
首先要要清楚的是高级界面为什么可以接受某些按键(如List可以接收Fire键,作为选中选项),高级界面其实都是由低级界面实现的,使用Canvas,你也可以定出自己的一套手机界面(如MyForm, MyList, MyTabbedForm),而其中如何响应按键呢?很简单了,重载Canvas的按键响应函数(keyPressed, keyReleased等)即可.
知道了高级界面的实现,大概可以猜到J2ME的高级界面中是怎样实现的了,查下Form的源码,可以看到keyPressed()函数,J2ME的keyPressed()函数在这里进行了重载,实现了接受按键,那么我们现在想做的就是扩展按键响应的功能,使之增加Fire键的支持,自然而然,我们会想到继承J2ME的高级界面类,再次重载keyPressed方法,的确,这种方法是可行的,这可是下面将面用的方法.
自定义的高级界面类作出了3个变化:
1. 重载了keyPressed方法
2. 提供注册方法RegisterItem(Item item, Command cmd)
3. 提供注销方法Unregister(Item item)
以MyForm为例,相关代码如下:
public MyForm(String title) {
super(title);
this.ht = new Hashtable();
}
public MyForm(String title, Style style)
{
super(title, style);
this.ht = new Hashtable();
}
public void RegisterItem(Item item, Command cmd)
{
ht.put(item, cmd);
}
public void UnregisterItem(Item item)
{
if(ht.containsKey(item))
ht.remove(item);
}
public void keyPressed(int key)
{
super.keyPressed(key);
int game = getGameAction(key);
if(game == FIRE)
{
Enumeration ite = ht.keys();
while (ite.hasMoreElements())
{
Item item = (Item)ite.nextElement();
if(item.isFocused)
{
UiAccess.handleCommand(item, (Command)ht.get(item));
}
}
}
}
}
其中RegisterItem将一个可以响应Fire键的Item注册到MyForm中,而响应Fire键的后续动作则映射到注册的命令cmd上,即对注册item点击Fire键将会执行commandItemListen中cmd的代码块。
可以看到,将Fire按键响应映射到cmd上是由polish中UiAccess包完成的,UiAccess.handleCommand(item, (command)ht.get(item)),即对控件item发布命令cmd,至于要执行哪些动作,则完全与命令响应一样。
一个简单的使用MyForm的例子:
private MyForm LoginScreen;
// command[命令]
private Command cmdSubmit;
public LoginUI()
{
super();
// command
this.cmdSubmit = new Command("登陆", Command.ITEM, 1);
// auxiliary
display();
}
/*------------------------------------------ react to user operation --------------------------------------- */
public void commandAction(Command c, Item item)
{
if(c == cmdSubmit)
{
system.out.println("Press cmd submit");
}
}
/*------------------------------------------ a set of auxiliary methods ----------------------------------- */
private void display()
{
//#style login_form
LoginScreen = new MyForm("登陆");
//LoginScreen = new MyForm("登陆");
//#style submit_login_item
IconItem submitItem = new IconItem(null, null);
submitItem.addCommand(cmdSubmit);
submitItem.setItemCommandListener(this);
submitContainer.add(submitItem);
// add together
LoginScreen.append(submitItem);
LoginScreen.RegisterItem(submitItem, cmdSubmit);
}
}
当选择IconItem,点击Fire键时,控制台会输出:Press cmd submit;响应成功。
要注意的是,对于一些高级界面,已经对部分按键作出了响应,因此要保证重写的高级界面对原有按键的响应不丢失,如在MyForm中,keyPressed中有这样一句话:super.keyPressed(key);首先响应父类的keyPressed函数。