J2ME简明教程( 第六章)

第六章 流程控制的设计模式
在LCDUI的架构下,画面上同时只能显示一个Displayable的子类实例。造成MIDP程序设计中,最令人头痛的地方莫过于程序的流程控制,也就是画面之间的切换。本章针对程序的流程控制,提出一种设计模式。让程序的流程控制能够更方便、更简单、更具可维护性。
一、 系统分析与设计
用户启动MIDlet——〉启动画面Splash
|
|
V
“版权” “开始” “说明”
版权声明<————>主画面 <————>游戏画面<————>辅助说明Help
| “返回”按钮 “返回”
|
| “设置”
<——————>设置画面<—————>辅助说明
| “返回”
|
| “离开”
|
V
分析画面特性:
1) 辅助说明:
每个辅助说明外观上大致相同,只有说明文字不同而已。用Form来实现。
2) 版权说明:
这类型的画面只是要给用户一些相关的说明信息。可以用Alert来实现。画面在整个系统中最好只有一个,除了可以保持本身状态,还可以降低内存的使用。
3) 主画面
方便用户操作,可以用IMPLICIT类型的List比较恰当。此画面在整个系统中最好只有一个,除了可以保持本身状态外,还可以降低内存的使用。
4) 设定画面
方便用户操作,用Form比较恰当。此画面在整个系统中最好只有一个。降低内存的使用。
5) 游戏画面
用Canvas来实现。此画面在系统中最好只有一个,保持本身状态,降低内存使用。
6) 启动画面
指在程序刚启动时用到,用Alert实现。
二、 流程控制器
将整个系统的流程控制交给一个统一的流程控制器来完成,流程控制器Navigator来实现。
由于系统的每个地方都需要用到MIDlet实例和Display实例,为避免重复编写程序,在Navigator中以midlet变量来存放系统中惟一个MIDlet实例(也就是主程序),以display变量存放惟一一个Display实例(屏幕对象)。这两个变量必须在MIDlet构造方法中予以初始化。
另外,为每一个画面定义一个常数整数,并使用current变量记录目前画面。这个变量必须在MIDlet的startApp()之中给予初始化。
//Navigator.java
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.util.* ;
public class Navigator
{
//为每一个画面定义一个常数整数
final public static int MAIN_SCREEN = 1 ;
final public static int GAME_SCREEN = 2 ;
final public static int SET_SCREEN = 3 ;
final public static int GAME_HELP_SCREEN = 4 ;
final public static int SET_HELP_SCREEN = 5 ;
//存放系统中惟一个MIDlet实例
public static MIDlet midlet ;
//存放惟一一个Display实例
public static Display display ;
//current变量记录目前画面
public static int current ;
public static void show(Object obj)
{
switch(current)
{
case MAIN_SCREEN :
break ;
case GAME_SCREEN :
break ;
case SET_SCREEN :
break ;
case GAME_HELP_SCREEN :
break ;
case SET_HELP_SCREEN :
break ;
}
}
public static void flow(String cmd)
{
switch(current)
{
case MAIN_SCREEN :
break ;
case GAME_SCREEN :
break ;
case SET_SCREEN :
break ;
case GAME_HELP_SCREEN :
break ;
case SET_HELP_SCREEN :
break ;
}
}
}
流程控制器中,并没有包含版权声明画面以及启动画面的流程控制。这是因为两者都使用Alert实现,Alert具有“时间一到就自然跳回前一个画面”的特性,因此我们不另外对其作流程控制比较好。
show()方法用来统一显示出画面,其obj参数是为了特殊用途(例如有些画面在显示前需要做一些初始化)。而flow()方法用来统一判断程序的流程,利用current变量与cmd变量,能轻易的判断目前程序的运作方向。
三、 画面的设计
把流程的控制权交给Navigator.flow()方法,Navigator.flow()方法内部会使用Navigator.show()方法来装换画面。
1、 用户触发事件——>画面(事件处理方法)——>2.流程判断
2、 流程判断(流程控制器):
flow() ——> 设定current
flow() ——> 切换画面show()
并非所有画面都用到这个方法切换,比方说整个系统的第一个画面,或是当我们用到线程的时候,就可能会直接调用show()帮我们显示画面。
在调用show()之前,别忘了先设定current变量,才能让程序正确的转换画面。
每个画面的实现:
1、 辅助说明
import javax.microedition.lcdui.* ;
public class HelpScreen extends Form implements CommandListener
{
public HelpScreen(String c)
{
super("辅助说明") ;
append(c) ;
addCommand(new Command("返回",Command.BACK,1)) ;
setCommandListener(this) ;
}
public void commandAction(Command c,Displayable s)
{
Navigator.flow(c.getLabel()) ;
}
}
2、 版权声明
在系统之中只有一个,使用Singleton模式实现。
import javax.microedition.lcdui.* ;
public class CopyScreen extends Alert
{
private static Displayable instance ;
synchronized public static Displayable getInstance()
{
if(instance == null)
instance = new CopyScreen() ;
return instance ;
}
private CopyScreen()
{
super("版权声明") ;
setString("此应用程序之版权属于XYZ公司所有") ;
setType(AlertType.INFO) ;
setTimeout(Alert.FOREVER) ;
}
}
3、 主画面
import javax.microedition.lcdui.* ;
public class MainScreen extends List implements CommandListener
{
private static Displayable instance ;
synchronized public static Displayable getInstance()
{
if(instance == null)
instance = new MainScreen() ;
return instance ;
}
private MainScreen()
{
super("版权声明",IMPLICIT) ;
append("开始",null) ;
append("设定",null) ;
append("版权声明",null) ;
append("离开",null) ;
setCommandListener(this) ;
}
public void commandAction(Command c,Displayable s)
{
String cmd = getString(getSelectedIndex()) ;
Navigator.flow(cmd) ;
}
}
4、 设置画面
import javax.microedition.lcdui.* ;
public class SetScreen extends Form implements CommandListener
{
private static Displayable instance ;
synchronized public static Displayable getInstance()
{
if(instance == null)
instance = new SetScreen() ;
return instance ;
}
TextField url ;
Gauge volume ;
private SetScreen()
{
super("设定") ;
url = new TextField("请输入服务器位置","socket://192.168.0.3:99",40,TextField.URL) ;
append(url) ;
volume = new Gauge("音量",true,10,3) ;
append(volume) ;
addCommand(new Command("辅助说明",Command.HELP,1)) ;
addCommand(new Command("返回",Command.BACK,1)) ;
setCommandListener(this) ;
}
public void commandAction(Command c,Displayable s)
{
Navigator.flow(c.getLabel()) ;
}
}
5、 游戏画面
import javax.microedition.lcdui.* ;
public class GameScreen extends Canvas implements CommandListener
{
private static Displayable instance ;
synchronized public static Displayable getInstance()
{
if(instance == null)
instance = new GameScreen() ;
return instance ;
}
private GameScreen()
{
addCommand(new Command("辅助说明",Command.HELP,1)) ;
addCommand(new Command("返回",Command.BACK,1)) ;
setCommandListener(this) ;
}
public void commandAction(Command c,Displayable s)
{
Navigator.flow(c.getLabel()) ;
}
public void paint(Graphics g)
{
g.setColor(125,125,125) ;
g.fillRect(0,0,getWidth(),getHeight()) ;
g.setColor(0,0,0) ;
g.drawRect(10,10,60,70) ;
}
}
四、完成流程控制器
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.util.* ;
public class Navigator
{
//为每一个画面定义一个常数整数
final public static int MAIN_SCREEN = 1 ;
final public static int GAME_SCREEN = 2 ;
final public static int SET_SCREEN = 3 ;
final public static int GAME_HELP_SCREEN = 4 ;
final public static int SET_HELP_SCREEN = 5 ;
//存放系统中惟一个MIDlet实例
public static MIDlet midlet ;
//存放惟一一个Display实例
public static Display display ;
//current变量记录目前画面
public static int current ;
public static void show(Object obj)
{
switch(current)
{
case MAIN_SCREEN :
display.setCurrent(MainScreen.getInstance()) ;
break ;
case GAME_SCREEN :
display.setCurrent(GameScreen.getInstance()) ;
break ;
case SET_SCREEN :
display.setCurrent(SetScreen.getInstance()) ;
break ;
case GAME_HELP_SCREEN :
display.setCurrent(new HelpScreen((String)obj)) ;
break ;
case SET_HELP_SCREEN :
display.setCurrent(new HelpScreen((String)obj)) ;
break ;
}
}
public static void flow(String cmd)
{
switch(current)
{
case MAIN_SCREEN :
if(cmd.equals("开始"))
{
current = GAME_SCREEN ;
show(null) ;
}else if(cmd.equals("设定"))
{
current = SET_SCREEN ;
show(null) ;
}else if(cmd.equals("版权声明"))
{
display.setCurrent(CopyScreen.getInstance()) ;
}else if(cmd.equals("离开"))
{
midlet.notifyDestroyed() ;
}
break ;
case GAME_SCREEN :
if(cmd.equals("辅助说明"))
{
current = GAME_HELP_SCREEN ;
show("游戏的操作方式") ;
}else if(cmd.equals("返回"))
{
current = MAIN_SCREEN ;
show(null) ;
}
break ;
case SET_SCREEN :
if(cmd.equals("辅助说明"))
{
current = SET_HELP_SCREEN ;
show("设定方式") ;
}else if(cmd.equals("返回"))
{
current = MAIN_SCREEN ;
show(null) ;
}
break ;
case GAME_HELP_SCREEN :
if(cmd.equals("返回"))
{
current = GAME_SCREEN ;
show(null) ;
}
break ;
case SET_HELP_SCREEN :
if(cmd.equals("返回"))
{
current = SET_SCREEN ;
show(null) ;
}
break ;
}
}
}
四、 MIDlet主程序设计
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class FlowControl extends MIDlet
{
boolean init = true ;
public FlowControl()
{
Navigator.display = Display.getDisplay(this) ;
Navigator.midlet = this ;
}
public void startApp()
{
Navigator.current = Navigator.MAIN_SCREEN ;
Navigator.show(null) ;
if(init)
{
Alert al = new Alert("片头画面") ;
al.setType(AlertType.CONFIRMATION) ;
al.setTimeout(5000) ;
Navigator.display.setCurrent(al) ;
init = false ;
}
}
public void pauseApp()
{
}
public void destroyApp(boolean con)
{
}
}
在系统每个地方都会用到MIDlet实体和Display实体,避免重复编写相同代码,这两个变量必须在MIDlet的构造方法中给与初始化。
另外,current变量必须在startApp()之中予以初始化。
init()变量判断startApp()是否第一次执行,只有第一次执行才显示启动画面。 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值