MIDP Command TextField TextBox Form代码分析

  在高级UI(比如Form或者List)上添加多个Command,在模拟器上和实际设备上的效果不同。TextField的输入效果,在模拟器和实际设备上也不同。它们为什么会有这种差异?能否实现一个控件,通过调用某个本地方法,实现TextField类似的效果?我要实现一个弹出的command List,能否参照MIDP的代码?带着这些疑问,我阅读了MIDP的相关代码。

    command相关的有二个疑问:    

    1.command是怎么绘制的?

    2.command是怎么响应的?

   TextField相关的也有一个疑问;

    1.TextField调用哪个本地方法,进入输入界面?

    2. 在本地输入的字符串如何传回来?

 

问题一:command是怎么绘制的?怎么响应的?

在之前的文章中,有分析过J2ME中高级UI的绘制。Form、List等继承自Screen,Screen和Canvas继承自Displayable,Displayable中实现了一个方法叫callpaint;Canvas重载了callpaint,在做了简单的坐标运算后,调用paint方法,而paint,由继承者实现。Form也重载了callpaint,在计算了坐标后,会遍历每个Item,调用Item的callPaint方法,继承自Item的TextField就重载了callPaint方法。

要搞清楚command是在哪里绘制的,首先要清楚它是在哪里被添加的。Displayable提供了addCommand的方法,我在Displayable中也发现了一个Command的数组用来存储添加的command。但是,在Displayable的callpaint方法中没有找到绘制command的部分,它提供了getCommands的方法,但是,在调用这个方法的地方也没有找到绘制的代码。它是在哪里被绘制的呢?

在Displayable.addcommand的实现中,调用了一个方法:updateCommandSet;

这个方法通过调用Display.updateCommandSet最终调用了一个本地方法:

 

public native void updateCommandSet(Command[] itemCommands, 

int numItemCommands,

Command[] commands, int numCommands);

这个方法将Command数组传给了本地,这让我怀疑command list的绘制是在本地绘制的!

 

 

在DefaultEventHandler中,有一个本地方法paintMenu,看起来很像。

如果就是这个方法,应该是这样一种逻辑:

在每次addCommand后,MIDP调用本地方法将command list传递给本地实现,在特殊的按键(一般是左右软键)发生后,本地实现会检查command list,如果有list,就发送一个command事件给MIDP,这个事件有两个值,一个值标识这是一个command type;另一个值标识这是一个MENU_REQUESTED;当MIDP收到这个事件后,就会暂停显示,进入menu模式,并调用本地方法paintMenu,显示这个menu list;在menu模式下,输入的信息都不会在MIDP处理;当选择某个command后,本地会再发送一个command事件给MIDP,这个事件有两个值,一个值标识这是一个command type;另一个值标识这个command的id;收到这个事件后,MIDP会推出menu模式,并调用相应的commandAction方法。

 

为了验证这个猜测,写了一个简单的Canvas,添加多个command,并重载了keypressed方法。当进入command list时,按某个key,发现keyPressed不会被调用。在实际设备上的测试结果验证了这个猜测。并发现Sun WTK在运行该测试程序时,出现了一个Bug。

 

DefaultEventHandler中还对KEY_EVENT、PEN_EVENT、SYSTEM_EVENT有类似的处理。

 

问题二:TextField调用了哪个本地方法?本地输入的字符串如何传回来?

在DefaultEventHandler中,对KEY_EVENT的处理由方法keyEvent完成。keyEvent有三个参数,type,str,code;

type标识这是KEY_EVENT的具体类型,code记录KEY_CODE,str记录了一个字符串。

对于普通的KEY TYPE,用参数key code;对于IME TYPE,用参数str。这个方法最终调用了Display.inputMethodEvent,最终将字符串传给了当前的TextField。这就是本地输入字符串传递的流程。

我在MIDP的code中没有找到TextField调用本地方法的代码。在TextField的构建中,获取了InputMethodHandler的引用:

 

 inputHandler = InputMethodHandler.getInputMethodHandler();

            inputClient  = new InputMethodClientImpl();

这个类的实现与平台是相关的,它从配置中读取信息:
String n = Configuration.getProperty(
                    "com.sun.midp.lcdui.inputMethodHandler");

 

默认的类是DefaultInputMethodHandler;在现有的平台上,我没有得到这个配置信息;手头的MIDP代码是参考代码,我想这是我没有找到本地方法的缘故。

TextField的实现,依然是有价值的。至少可以参照它实现自己的TextField,实现英文和数字的输入法。

 

另一个结论是,不能使用TextField类似的流程来封装输入控件,除非可以添加本地方法并修改MIDP的代码。

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值