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 class MyForm extends Form{ private Hashtable ht; 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的例子:
public class LoginUI implements ItemCommandListener { 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函数。