分享
 
 
 

如何实现j2me对话框

王朝java/jsp·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

内容提要:

在手机这么小的屏幕上开发应用,难点之一就是频繁的屏幕切换。尽管midp2.0的UI部分已经很丰富了,但这些UI部件都是基于事件回调的。这在处理大量的、简单的问答式交互时显得力不从心。

本文实现了一个阻塞当前线程的对话框,简要地说,你可以使用诸如win32API中dialog函数那样的方式来实现对话框并阻塞等待返回值,然后根据返回值进行不同的处理。听起来很诱人吧。

正文:

问题何在?

首先回顾一下midp UI的事件处理机制。有两个要点:

1)首先UI部分由系统的一个线程负责维护。也就是说不能阻塞系统的事件处理方法。

2)事件处理使用的是一种回调机制。首先UI部件使用诸如setCommandListener之类的方法为自己注册一个回调接口(其中的回调方法由用户实现);等到触发了相应事件就调用这个注册好的接口的回调方法。

以下是一个实现了CommandListener的类的代码片断:

Form f=new Form("Hello world");

f.addCommand(exit);

f.setCommandListener(this);

可以想象基于事件回调的处理方式,在处理大量的、简单的问答式交互时显得力不从心。你不得不为每一个仅仅是询问要不要继续的对话框而实现一个又一个类,或者处理一个复杂的回调函数。如果选择后者,那么在一个又一个的if-else中处理不同逻辑事件的代码片断一定会烦死你。

较好的做法

这时候我们不免怀念一下win32 Api中对话框函数的处理方式:

int choose=Dialog(title,type……);

if(choose==OK){……}

else if(choose==Cancel){……}

这样处理将会阻塞当前线程,等待返回值,然后根据返回值进行处理。这样做很cool的原因就是在一个逻辑性很完整的任务中,你可以一次性在一个回调方法中完成所有逻辑,而不必为了问询简单的YES/NO问题而在不同的类中间跳来跳去。

如何在MIDP下实现

我们遇到的第一个问题来自于我们的方法必须要阻塞当前线程等待返回值。也就是说,这个对话框不能在UI的回调中直接运行,比如commandAction中。解决办法是将所有的事件处理都放到一个线程类中处理。(这是一点额外的负担,但不可避免)。还好这个工作量不大,要想实现两个对象之间的通信也不难。

第二个问题是如何阻塞当前的线程,我们祭出java线程的三板斧之wait()/notifyAll()。我们可以指定一个信号量(初值false),当其为false时阻塞当前线程,在得到用户通知后将信号量改为true,并唤醒线程。

下面看一下主要思路:

看一下代码:

Dialog.java

/*

*为j2me提供阻塞的dialog调用方法。

*但前提是,如果要在UI的相应线程中运行(比如commonAction),

*则需首先打开一个新的线程中使用,因为UI线程是不可以阻塞的。

*这个版本虽然包含在coreUI2.0中,但midp1.0也可以用。seimens s57通过测试。

*

*/

package bean;

import javax.microedition.lcdui.Command;

import javax.microedition.lcdui.CommandListener;

import javax.microedition.lcdui.Display;

import javax.microedition.lcdui.Displayable;

import javax.microedition.lcdui.Form;

/**

* @author Favo

*/

public class Dialog {//主类

PRivate boolean blockFlag = false;

public static int YES=0;

public static int NO=1;

private int returnValue;

private Display display;

public Dialog(Display display){

this.display=display;

}

public void setReturnValue(int i){//设置返回值

returnValue=i;

}

synchronized boolean getBlockFlag() {//取得信号量

return blockFlag;

}

synchronized void setBlockFlag(boolean flag) {//设置信号量

blockFlag = flag;

}

public int show(String title,String content,String yes,String no){

setBlockFlag(false);

Form f=new DialogForm(this,title,content,yes,no);

display.setCurrent(f);//显示UI

try {

while(getBlockFlag()==false){//如果用户没选择阻塞

synchronized (this) {

wait();

}

}

} catch (InterruptedException e) {

e.printStackTrace();

System.out.println("InterruptedException in Dialog.show");

}

return returnValue;//返回

}

public void wakeup(){

synchronized (this) {//唤醒阻塞的线程

notifyAll();

}

}

}

class DialogForm extends Form implements CommandListener{//UI部分

Command yesCMD;

Command noCMD;

Dialog dialog;

public DialogForm(Dialog dialog,String title,String content,String yes,String no) {

super(title);

this.dialog=dialog;

append(content);

yesCMD=new Command(yes,Command.OK,1);

noCMD=new Command(no,Command.CANCEL,1);

addCommand(yesCMD);

addCommand(noCMD);

setCommandListener(this);

}

public void commandAction(Command c, Displayable d) {

if(c==yesCMD){

dialog.setBlockFlag(true);

dialog.setReturnValue(Dialog.YES);

dialog.wakeup();

}else if(c==noCMD){

dialog.setBlockFlag(true);

dialog.setReturnValue(Dialog.NO);

dialog.wakeup();

}

}

}

如何使用

我编写了一个Test。当用户按下show按钮时,开启对话框,并将用户的选择打印出来。

DialogTest.java

package bean;

import javax.microedition.lcdui.Command;

import javax.microedition.lcdui.CommandListener;

import javax.microedition.lcdui.Display;

import javax.microedition.lcdui.Displayable;

import javax.microedition.lcdui.Form;

import javax.microedition.midlet.MIDlet;

import javax.microedition.midlet.MIDletStateChangeException;

public class DialogTest extends MIDlet implements CommandListener {

Display display;

Form f = new Form("DialogTest");

Command showCMD = new Command("show", Command.ITEM, 1);

public DialogTest() {

super();

display = Display.getDisplay(this);

f.addCommand(showCMD);

f.setCommandListener(this);

display.setCurrent(f);

}

protected void startApp() throws MIDletStateChangeException {

}

protected void pauseApp() {

}

protected void destroyApp(boolean arg0) throws MIDletStateChangeException {

}

public void commandAction(Command c, Displayable d) {

new work1(c).start();

}

class work1 extends Thread {

Command c;

public work1(Command c) {

super();

this.c = c;

}

public void run() {

super.run();

if(c==showCMD){

int choose=new Dialog(display).show("Choose","Do you like your Operation?","yes","no");

if(choose==Dialog.YES){

f.append("Yes,user like\n");

}else if(choose==Dialog.NO){

f.append("No,user like\n");

}

display.setCurrent(f);

}

}

}

}

屏幕快照

按下show

用户多次选择的结果

(出处:http://www.knowsky.com)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有