JavaMe开发:也说MVC设计模式

开发 后端
介绍设计模式的文章和书很多,但只有使用时,才能理解设计模式的妙处。接上一篇《JavaMe连载(2)-低级界面绘图之菜单》,本文一则对UIController作出解释,一则将自己理解的MVC设计模式,结合实例,与大家交流学习。

【更新】本文将适时做出更新,所以现在不是终稿,如有不当之处,敬请指出。

【问题描述】介绍设计模式的文章和书很多,但只有使用时,才能理解设计模式的妙处。接上一篇《JavaMe连载(2)-低级界面绘图之菜单》,本文一则对UIController作出解释,一则将自己理解的MVC设计模式,结合实例,与大家交流学习。

【理论】什么是MVC?

MVC就是模型(model)、视图(view)和控制(control)。什么是模型呢?本例中,模型就是对数据使用时的封装。视图很容易理解,那就是显示内容的具体表示。控制呢?有很多人对视图和控制分不清。在本例中,控制包含视图控制器以及方法的封装。

【实例】

1、先看工程结构,如图1所示。

 


图1 工程结构

工程中将用户数据单独封装,作为model。供控制器和视图调用。将显示页面单独封装,作为视图。将视图控制器UIController和常用方法封装为util。UIController就是控制。

2、UML图(后续更新时补充)

 

先看代码,再分析工作机理

【代码清单】

MainMidlet.java

  1. package com.token.midlet;  
  2.  
  3. import java.io.IOException;  
  4.  
  5. import javax.microedition.lcdui.*;  
  6. import javax.microedition.midlet.MIDlet;  
  7. import javax.microedition.midlet.MIDletStateChangeException;  
  8. import com.token.util.UIController;  
  9.  
  10. public class MainMidlet extends MIDlet {  
  11.       
  12.     private Display display;  
  13.     private static UIController controller;  
  14.     public MainMidlet() {  
  15.         // TODO Auto-generated constructor stub  
  16.         super();  
  17.         display=Display.getDisplay(this);  
  18.           
  19.     }  
  20.  
  21.     /* (non-Javadoc)  
  22.      * @see javax.microedition.midlet.MIDlet#pauseApp()  
  23.      */ 
  24.     protected void startApp() throws MIDletStateChangeException {  
  25.         controller=new UIController(this);  
  26.         try {  
  27.             controller.init();  
  28.         } catch (IOException e) {  
  29.             // TODO Auto-generated catch block  
  30.             e.printStackTrace();  
  31.         }//初始化RecordStore  
  32.     }  
  33.  
  34.     /* (non-Javadoc)  
  35.      * @see javax.microedition.midlet.MIDlet#pauseApp()  
  36.      */ 
  37.     protected void pauseApp() {  
  38.         this.notifyPaused();  
  39.     }  
  40.  
  41.     /* (non-Javadoc)  
  42.      * @see javax.microedition.midlet.MIDlet#destroyApp(boolean)  
  43.      */ 
  44.     protected void destroyApp(boolean arg0) throws MIDletStateChangeException {  
  45.         controller=null;  
  46.           
  47.     }  
  48.       
  49.     public void setCurrent(Displayable disp){  
  50.         display.setCurrent(disp);  
  51.     }  
  52.       
  53.     public void setCurrent(Alert alert, Displayable disp){  
  54.         display.setCurrent(alert, disp);  
  55.     }  
  56.     public Displayable getCurrent(){  
  57.         return display.getCurrent();  
  58.     }  
  59.       
  60.     public void exit(boolean arg0){  
  61.         try{  
  62.             destroyApp(arg0);  
  63.             notifyDestroyed();  
  64.         }catch(MIDletStateChangeException e){  
  65.             //  
  66.         }  
  67.     }  
  68.  
  69. }  

模型(Model)

UserDataItem.java

  1. package com.token.model;  
  2.  
  3. import com.token.util.StringDealMethod;  
  4.  
  5. public class UserDataItem {  
  6.     private int id;  
  7.     public String name = null;  
  8.     public String passwd = null;  
  9.  
  10.     public UserDataItem(String name,String passwd)  
  11.     {  
  12.         this.name = name;  
  13.         this.passwd = passwd;     
  14.     }  
  15.       
  16.     public UserDataItem(int id,byte[] data){  
  17.         this.id=id;  
  18.         String temp=new String(data);  
  19.         String temp_sub[] = StringDealMethod.split(temp, ",");  
  20.         this.name = temp_sub[0];  
  21.         this.passwd = temp_sub[1];  
  22.     }  
  23.       
  24.     public int getId(){  
  25.         return id;  
  26.     }  
  27.       
  28.     public void setId(int id){  
  29.         this.id=id;  
  30.     }  
  31.       
  32.     public String getName(){  
  33.         return name;  
  34.     }  
  35.       
  36.     public void setName(String name){  
  37.         this.name = name;  
  38.     }  
  39.       
  40.     public String getPasswd(){  
  41.         return passwd;  
  42.     }  
  43.       
  44.     public void setPasswd(String passwd){  
  45.         this.passwd = passwd;  
  46.     }  
  47.       
  48.     public byte[] getBytes(){  
  49.         String temp=null;  
  50.           
  51.         if(name==null||passwd==null){  
  52.             return null;  
  53.         }else{  
  54.             temp=name+","+passwd;  
  55.         }  
  56.           
  57.         return temp.getBytes();  
  58.     }  
  59. }  

控制(control)

UIController.java

  1. package com.token.util;  
  2.  
  3. import java.io.IOException;  
  4.  
  5. import javax.microedition.lcdui.*;  
  6.  
  7. import com.token.midlet.MainMidlet;  
  8. import com.token.model.*;  
  9. import com.token.view.*;  
  10. //import com.token.view.components.Color;  
  11.  
  12. public class UIController {  
  13.  
  14.     private MainMidlet midlet;  
  15.       
  16.     private TokenDataRecord tokenRecord;  
  17.       
  18.     private WelcomeScreen welcomeScreen;  
  19.     private UserRegist reg;   
  20.     private ActiveScreen activeScreen;  
  21.     private MainScreen mainScreen;  
  22.     private GenPasswd gen;  
  23.     private CheckScreen check;  
  24.     private ViewToken viewToken;  
  25.     private UserManage manage;  
  26.     private ShowHelp help;  
  27.     private UserAuth auth;  
  28.     private PopUpTextBox textBox;  
  29.       
  30.     int id = 1;  
  31.       
  32.     public UIController(MainMidlet midlet)  
  33.     {  
  34.         this.midlet = midlet;  
  35.           
  36.         tokenRecord = new TokenDataRecord();  
  37.     }  
  38.       
  39.     public void init() throws IOException{  
  40.           
  41.         try {  
  42.             SplashScreen splashScreen = new SplashScreen();  
  43.             setCurrent(splashScreen);  
  44.             Thread.sleep(1000);  
  45.               
  46.             Configure.configureColor();  
  47.             initObject();     
  48.               
  49.             //tokenRecord.db_deleteAllRecord();  
  50.             if(tokenRecord.db_getRecord(1)==null)  
  51.             {  
  52.                 //System.out.println("add");  
  53.                 ChaosMethods method = new ChaosMethods();  
  54.                 TokenDataItem tokenItem = new TokenDataItem(1,(method.ChaosInitCode()+",false").getBytes());  
  55.                 id=tokenRecord.db_addRecord(tokenItem);  
  56.             }  
  57.               
  58.             //System.out.println(id);  
  59.             TokenDataItem tokenItem1 = tokenRecord.db_getRecord(id);  
  60.             //System.out.println(tokenItem1.token+","+tokenItem1.isActive);  
  61.               
  62.             if(tokenItem1.getStatus().equals("false"))  
  63.             {  
  64.                 this.handleEvent(UIController.EventID.EVENT_NEXT_WELCOME_SCREEN,null);  
  65.             }else 
  66.             {  
  67.                 String flag = "0";  
  68.                 Object [] args = {flag,""};  
  69.                 this.handleEvent(UIController.EventID.EVENT_MAIN_SCREEN,args);  
  70.             }  
  71.         } catch (InterruptedException e) {  
  72.             // TODO Auto-generated catch block  
  73.             e.printStackTrace();  
  74.         }  
  75.           
  76.     }  
  77.       
  78.     private void initObject()  
  79.     {  
  80.         welcomeScreen = new WelcomeScreen(this);  
  81.         reg= new UserRegist(this);  
  82.         activeScreen = new ActiveScreen(this);  
  83.         ...  
  84.         textBox = new PopUpTextBox(this,"输入文本",""1000, TextField.ANY);  
  85.     }  
  86.       
  87.     //getMethod  
  88.     public void setCurrent(Displayable disp){  
  89.         midlet.setCurrent(disp);  
  90.     }  
  91.     public void setCurrent(Alert alert, Displayable disp){  
  92.         midlet.setCurrent(alert, disp);  
  93.     }  
  94.       
  95.     //定义事件ID内部类  
  96.     public static class EventID{  
  97.         private EventID(){  
  98.         }  
  99.           
  100.         public static final byte EVENT_EXIT = 0;//退出  
  101.         public static final byte EVENT_NEXT_WELCOME_SCREEN = 1;//欢迎界面  
  102.         public static final byte EVENT_NEXT_USER_REGIST_SCREEN = 2;//用户注册  
  103.         public static final byte EVENT_USER_REGIST_EDIT = 3;//用户注册编辑  
  104.         public static final byte EVENT_USER_REGIST_EDIT_BACK = 4;//用户注册编辑返回  
  105.         public static final byte EVENT_NEXT_ACTIVE_SCREEN = 5;  
  106.        //...  
  107.     }  
  108.       
  109.     //事件处理  
  110.     public void handleEvent( int eventID, Object[] args)  
  111.     {  
  112.         switch (eventID)  
  113.         {     
  114.             case EventID.EVENT_EXIT:  
  115.             {  
  116.                 midlet.exit(false);  
  117.                 break;  
  118.             }  
  119.             case EventID.EVENT_NEXT_WELCOME_SCREEN:  
  120.             {  
  121.                     welcomeScreen.show();  
  122.                 midlet.setCurrent(welcomeScreen);  
  123.                 break;  
  124.             }  
  125.             case EventID.EVENT_NEXT_USER_REGIST_SCREEN:  
  126.             case EventID.EVENT_USER_REGIST_EDIT_BACK:  
  127.             {  
  128.                 reg.show(args);  
  129.                 Thread thread = new Thread(reg);  
  130.                 thread.start();  
  131.                 midlet.setCurrent(reg);  
  132.                 break;  
  133.             }  
  134.             case EventID.EVENT_USER_REGIST_EDIT:  
  135.             {  
  136.                 textBox.init(args);  
  137.                 midlet.setCurrent(textBox);  
  138.                 break;  
  139.             }  
  140.             case EventID.EVENT_NEXT_ACTIVE_SCREEN:  
  141.             {  
  142.                 activeScreen.show(args);  
  143.                 Thread thread = new Thread(activeScreen);  
  144.                 thread.start();  
  145.                 midlet.setCurrent(activeScreen);  
  146.                 break;  
  147.             }  
  148.             //...  
  149.             default:  
  150.                 break;  
  151.         }  
  152.     }  
  153. }  

#p#

UserDataRecord.java

  1. package com.token.util;  
  2.  
  3. import java.util.Vector;  
  4.  
  5. import javax.microedition.rms.RecordComparator;  
  6. import javax.microedition.rms.RecordEnumeration;  
  7. import javax.microedition.rms.RecordStore;  
  8. import javax.microedition.rms.RecordStoreException;  
  9.  
  10. import com.token.model.*;  
  11.  
  12. public class UserDataRecord {  
  13.     private static final String RECORDSTORE_NAME="USER_DB";  
  14.     private static RecordStore info;  
  15.       
  16.     public UserDataRecord(){  
  17.     }  
  18.       
  19.     //打开RecordStore,没有则创建  
  20.     public void openDataBase() {  
  21.         try {  
  22.             info = RecordStore.openRecordStore(RECORDSTORE_NAME, true);  
  23.         }catch (RecordStoreException ex) {              
  24.             info =null;  
  25.         }  
  26.     }  
  27.     //关闭RecordStore  
  28.     public void closeDataBase() {  
  29.         if (info!= null) {  
  30.             try {  
  31.                 info.closeRecordStore();  
  32.                 info=null;  
  33.             } catch (RecordStoreException ex) {}  
  34.         }  
  35.     }  
  36.     //增加记录  
  37.     public int db_addRecord(UserDataItem item) {  
  38.                      
  39.                 try {  
  40.                     this.openDataBase();  
  41.                     byte[] data=item.getBytes();  
  42.                     int id=info.getNextRecordID();  
  43.                     info.addRecord(data,0,data.length);  
  44.                     this.closeDataBase();  
  45.                     return id;  
  46.                 } catch (RecordStoreException ex) { }  
  47.           
  48.         return -1;  
  49.     }  
  50.     //更新记录  
  51.     public void db_updateRecord(UserDataItem item){  
  52.  
  53.             try {  
  54.                 this.openDataBase();        
  55.                 byte[] data=item.getBytes();  
  56.                 info.setRecord(item.getId(),data,0,data.length);  
  57.                 this.closeDataBase();  
  58.             } catch (RecordStoreException ex) { }  
  59.     }  
  60.     //访问一条记录  
  61.     public UserDataItem db_getRecord(int id){  
  62.         UserDataItem item=null;  
  63.  
  64.             try {  
  65.                 this.openDataBase();  
  66.                 item = new UserDataItem(id,info.getRecord(id));  
  67.                 this.closeDataBase();  
  68.             } catch (RecordStoreException ex) { }  
  69.  
  70.          return item;  
  71.     }  
  72.     //删除一条记录  
  73.     public void db_deleteRecord(int id){  
  74.             try {  
  75.                 this.openDataBase();  
  76.                 info.deleteRecord(id);  
  77.                 this.closeDataBase();  
  78.             } catch (RecordStoreException ex) {}  
  79.     }  
  80.       
  81.     //删除所有记录  
  82.     public void db_deleteAllRecord(){  
  83.             try {  
  84.                 RecordStore.deleteRecordStore(RECORDSTORE_NAME);  
  85.             } catch (RecordStoreException ex) {}  
  86.     }  
  87.       
  88.     //访问所有记录  
  89.     public Vector db_getRecords(){  
  90.         Vector items=new Vector(10,3);  
  91.         this.openDataBase();//打开RecordStore  
  92.         RecordEnumeration enum1=null;  
  93.         int ind=0;  
  94.         try{  
  95.             UserDataItem item=null;  
  96.             enum1=info.enumerateRecords(null,new InnerComparator(),false);  
  97.               
  98.             while(enum1.hasPreviousElement()){  
  99.                 ind=enum1.previousRecordId();  
  100.                 item=new UserDataItem(ind,info.getRecord(ind));  
  101.                 items.addElement(item);  
  102.             }  
  103.               
  104.         }catch(Exception ex){ex.printStackTrace();}  
  105.         finally{  
  106.                 try{  
  107.                     enum1.destroy();  
  108.                 }catch(Exception e){}  
  109.                   
  110.                 this.closeDataBase();//关闭RecordStore  
  111.         }//end finally  
  112.       
  113.         return items;  
  114.     }  
  115.     //一个简单的比较器  
  116.     private class InnerComparator implements RecordComparator{  
  117.         public int compare(byte[] rec1, byte[] rec2){  
  118.             if(rec1.length>rec2.length)  
  119.                 return FOLLOWS;  
  120.             else if(rec1.length<rec2.length)  
  121.                 return PRECEDES;  
  122.             else   
  123.                 return EQUIVALENT;  
  124.         }  
  125.  
  126.     }  
  127. }  

视图(view)

WelcomeScreen.java

  1. package com.token.view;  
  2.  
  3. import javax.microedition.lcdui.*;  
  4. import javax.microedition.lcdui.game.GameCanvas;  
  5.  
  6. import com.token.util.UIController;  
  7. import com.token.util.StringDealMethod;  
  8. import com.token.view.components.*;  
  9.  
  10.  
  11. public class WelcomeScreen extends GameCanvas {  
  12.  
  13.     private UIController controller;  
  14.     private Graphics graphics;  
  15.     private Font ft;  
  16.     private String info;  
  17.     private String info_wrap[];  
  18.     private int width;  
  19.     private int height;  
  20.       
  21.     private Menu menu;  
  22.     private Head head;  
  23.     private BackGroud backGroud;  
  24.       
  25.     public WelcomeScreen(UIController control) {  
  26.         // TODO Auto-generated constructor stub  
  27.         super(false);  
  28.         controller=control;  
  29.         setFullScreenMode(true);  
  30.         graphics = getGraphics();  
  31.           
  32.         width = getWidth();  
  33.         height = getHeight();  
  34.           
  35.         menu = new Menu(this);  
  36.         head = new Head(this);  
  37.         backGroud = new BackGroud(this);  
  38.     }  
  39.  
  40.     public void show() {  
  41.         // TODO Auto-generated method stub  
  42.         //clearScreen();  
  43.         backGroud.drawBackGroud(this, graphics);  
  44.         head.drawHead(this,graphics,"");  
  45.         menu.drawMenu(this, graphics,"下一步","退出");  
  46.         drawBody();  
  47.     }  
  48.       
  49.     public void drawBody()  
  50.     {  
  51.         ft = Font.getFont(Font.FACE_PROPORTIONAL,Font.STYLE_BOLD,Font.SIZE_LARGE);  
  52.           
  53.         info = "欢迎使用!\n" 
  54.                 +"1 MVC测试;\n" 
  55.                 +"2 自动换行测试,绘制可自动识别换行的字符串。\n";  
  56.         info_wrap = StringDealMethod.format(info, width-10, ft);  
  57.           
  58.         graphics.setColor(Color.text);  
  59.         graphics.setFont(ft);  
  60.         for(int i=0; i<info_wrap.length; i++)  
  61.         {  
  62.             graphics.drawString(info_wrap[i], 5, i * ft.getHeight()+40, Graphics.TOP|Graphics.LEFT);  
  63.         }  
  64.     }  
  65.       
  66.     public void clearScreen()  
  67.     {  
  68.         graphics.setColor(0xff,0xff,0xff);  
  69.         graphics.fillRect(00, width, height);  
  70.     }  
  71.       
  72.     protected void keyPressed(int keycode)  
  73.     {  
  74.         switch(keycode)  
  75.         {  
  76.             case KeyID.SOFT_RIGHT:  
  77.             {  
  78.                 controller.handleEvent(UIController.EventID.EVENT_EXIT,null);  
  79.                 break;  
  80.             }  
  81.             case KeyID.SOFT_LEFT:  
  82.             {  
  83.                 String editor = "regist_name";  
  84.                 Object [] args = {"registScreen",editor, null,null,null};  
  85.                 controller.handleEvent(UIController.EventID.EVENT_NEXT_USER_REGIST_SCREEN,args);  
  86.                 break;  
  87.             }  
  88.             default:;  
  89.         }  
  90.     }  
  91.       
  92. }  

UserRegist.java

  1. package com.token.view;  
  2.  
  3. import javax.microedition.lcdui.Font;  
  4. import javax.microedition.lcdui.Graphics;  
  5. import javax.microedition.lcdui.game.GameCanvas;  
  6. import com.token.model.*;  
  7. import com.token.util.*;  
  8. import com.token.view.components.*;  
  9.  
  10. public class UserRegist extends GameCanvas implements Runnable {  
  11.  
  12.     private UIController controller;  
  13.     private Graphics graphics;  
  14.       
  15.     private Font ft;  
  16.       
  17.     private Menu menu;  
  18.     private Head head;  
  19.     private BackGroud backGroud;  
  20.       
  21.     private UserDataRecord userRecord;  
  22.  
  23.     private String title;  
  24.       
  25.     private TextEdit textEdit_name;  
  26.     private TextEdit textEdit_passwd;  
  27.     private TextEdit textEdit_passwd_re;  
  28.     private int textEdit_name_x;  
  29.     private int textEdit_name_y;  
  30.     private int textEdit_passwd_x;  
  31.     private int textEdit_passwd_y;  
  32.     private int textEdit_passwd_re_x;  
  33.     private int textEdit_passwd_re_y;  
  34.     private int currentlySelectedIndex = 0;  
  35.       
  36.     private String username;  
  37.     private String passwd;  
  38.     private String passwd_re;  
  39.       
  40.     long caretBlinkDelay = 500L;  
  41.     long lastCaretBlink = 0;  
  42.     private String object_name;  
  43.     private String editor;  
  44.     private boolean cursorBlinkOn1;  
  45.     private boolean cursorBlinkOn2;  
  46.     private boolean cursorBlinkOn3;  
  47.       
  48.     private int width;  
  49.     private int height;  
  50.       
  51.     public UserRegist(UIController control)   
  52.     {  
  53.         super(false);  
  54.         this.controller=control;  
  55.         this.title = "用户注册";  
  56.         setFullScreenMode(true);  
  57.         graphics = getGraphics();  
  58.           
  59.         width = getWidth();  
  60.         height = getHeight();  
  61.           
  62.         menu = new Menu(this);  
  63.         head = new Head(this);  
  64.         backGroud = new BackGroud(this);  
  65.           
  66.         userRecord = new UserDataRecord();  
  67.           
  68.         textEdit_name = new TextEdit(this);  
  69.         textEdit_passwd = new TextEdit(this);  
  70.         textEdit_passwd_re = new TextEdit(this);  
  71.     }  
  72.  
  73.     public void show(Object[] args) {  
  74.         // TODO Auto-generated method stub  
  75.         setFullScreenMode(true);  
  76.           
  77.         object_name = ((String)args[0]!=null)?(String)args[0]:"";  
  78.         editor = ((String)args[1]!=null)?(String)args[1]:"";  
  79.         username = ((String)args[2]!=null)?(String)args[2]:"";  
  80.         passwd = ((String)args[3]!=null)?(String)args[3]:"";  
  81.         passwd_re = ((String)args[4]!=null)?(String)args[4]:"";  
  82.           
  83.         if(editor.equals("regist_name"))  
  84.         {  
  85.             cursorBlinkOn1 = true;  
  86.             cursorBlinkOn2 = false;  
  87.             cursorBlinkOn3 = false;  
  88.             currentlySelectedIndex =0;  
  89.         }  
  90.         else if(editor.equals("regist_passwd"))  
  91.         {  
  92.             cursorBlinkOn1 = false;  
  93.             cursorBlinkOn2 = true;  
  94.             cursorBlinkOn3 = false;  
  95.             currentlySelectedIndex =1;  
  96.         }  
  97.         else if(editor.equals("regist_passwd_re"))  
  98.         {  
  99.             cursorBlinkOn1 = false;  
  100.             cursorBlinkOn2 = false;  
  101.             cursorBlinkOn3 = true;  
  102.             currentlySelectedIndex =2;  
  103.         }  
  104.           
  105.         //System.out.println(object_name);  
  106.         //System.out.println(editor);  
  107.         draw();  
  108.         redraw();  
  109.     }  
  110.  
  111.     public void draw()  
  112.     {  
  113.         //clearScreen();  
  114.         backGroud.drawBackGroud(this, graphics);  
  115.         head.drawHead(this,graphics,this.title);  
  116.         menu.drawMenu(this,graphics,"下一步","退出");  
  117.         drawBody();  
  118.     }  
  119.  
  120.     private void redraw()  
  121.     {  
  122.         switch(currentlySelectedIndex)  
  123.         {  
  124.             case 0:  
  125.             {  
  126.                 cursorBlinkOn2 = false;  
  127.                 cursorBlinkOn3 = false;  
  128.                 editor = "regist_name";  
  129.                 break;  
  130.             }  
  131.             case 1:  
  132.             {  
  133.                 cursorBlinkOn1 = false;  
  134.                 cursorBlinkOn3 = false;  
  135.                 editor = "regist_passwd";  
  136.                 break;  
  137.             }  
  138.             case 2:  
  139.             {  
  140.                 cursorBlinkOn1 = false;  
  141.                 cursorBlinkOn2 = false;  
  142.                 editor = "regist_passwd_re";  
  143.                 break;  
  144.             }  
  145.             default:;  
  146.         }  
  147.           
  148.         textEdit_name.drawTextBox(this, graphics, username, textEdit_name_x, textEdit_name_y, cursorBlinkOn1);  
  149.         textEdit_passwd.drawTextBox(this, graphics, passwd, textEdit_passwd_x, textEdit_passwd_y, cursorBlinkOn2);  
  150.         textEdit_passwd.drawTextBox(this, graphics, passwd_re, textEdit_passwd_re_x, textEdit_passwd_re_y, cursorBlinkOn3);  
  151.         textEdit_name.flushGraphics();  
  152.     }  
  153.  
  154.     public void drawBody()  
  155.     {  
  156.         int margin =5;  
  157.         ft = Font.getFont(Font.FACE_PROPORTIONAL,Font.STYLE_BOLD,Font.SIZE_LARGE);  
  158.           
  159.         String info = "用户名:\n";  
  160.         String info_wrap1[] = StringDealMethod.format(info, width-10, ft);  
  161.           
  162.         graphics.setFont(ft);  
  163.         graphics.setColor(Color.text);  
  164.         for(int i=0; i<info_wrap1.length; i++)  
  165.         {  
  166.             graphics.drawString(info_wrap1[i],5, (i) * ft.getHeight()+40, Graphics.TOP|Graphics.LEFT);  
  167.         }  
  168.           
  169.         textEdit_name_x = 5;  
  170.         textEdit_name_y = info_wrap1.length * ft.getHeight()+40;  
  171.         textEdit_name.drawTextBox(this, graphics, username, textEdit_name_x, textEdit_name_y, cursorBlinkOn1);  
  172.           
  173.         info = "用户密码:\n";  
  174.         String info_wrap2[] = StringDealMethod.format(info, width-10, ft);  
  175.       
  176.         graphics.setFont(ft);  
  177.         graphics.setColor(Color.text);  
  178.         for(int i=0; i<info_wrap2.length; i++)  
  179.         {  
  180.             graphics.drawString(info_wrap2[i],5, (i+info_wrap1.length) * ft.getHeight()+textEdit_name.height+margin+40, Graphics.TOP|Graphics.LEFT);  
  181.         }  
  182.           
  183.         textEdit_passwd_x = 5;  
  184.         textEdit_passwd_y = (info_wrap1.length+info_wrap2.length) * ft.getHeight()+textEdit_name.height+margin+40;  
  185.         textEdit_passwd.drawTextBox(this, graphics, passwd, textEdit_passwd_x, textEdit_passwd_y, cursorBlinkOn2);  
  186.       
  187.         info = "密码确认:\n";  
  188.         String info_wrap3[] = StringDealMethod.format(info, width-10, ft);  
  189.       
  190.         graphics.setFont(ft);  
  191.         graphics.setColor(Color.text);  
  192.         for(int i=0; i<info_wrap3.length; i++)  
  193.         {  
  194.             graphics.drawString(info_wrap3[i],5, (i+info_wrap1.length+info_wrap2.length) * ft.getHeight()+textEdit_name.height+textEdit_passwd.height+2*margin+40, Graphics.TOP|Graphics.LEFT);  
  195.         }  
  196.           
  197.         textEdit_passwd_re_x = 5;  
  198.         textEdit_passwd_re_y = (info_wrap1.length+info_wrap2.length+info_wrap3.length) * ft.getHeight()+textEdit_name.height+textEdit_passwd.height+2*margin+40;  
  199.         textEdit_passwd_re.drawTextBox(this, graphics, passwd_re, textEdit_passwd_re_x, textEdit_passwd_re_y, cursorBlinkOn3);  
  200.       
  201.           
  202.     }  
  203.  
  204.     public void clearScreen()  
  205.     {  
  206.         graphics.setColor(0xff,0xff,0xff);  
  207.         graphics.fillRect(00, width, height);  
  208.     }  
  209.  
  210.     public void checkTimeStamp()  
  211.     {  
  212.         long currentTime = System.currentTimeMillis();  
  213.         //System.out.println("1");  
  214.         if(lastCaretBlink + caretBlinkDelay < currentTime)  
  215.         {  
  216.             //System.out.println("2");  
  217.             if(editor.equals("regist_name"))  
  218.             {  
  219.                 cursorBlinkOn1 =! cursorBlinkOn1;  
  220.                 cursorBlinkOn2 = false;  
  221.                 cursorBlinkOn3 = false;  
  222.             }  
  223.             else if(editor.equals("regist_passwd"))  
  224.             {  
  225.                 cursorBlinkOn1 = false;  
  226.                 cursorBlinkOn2 =! cursorBlinkOn2;  
  227.                 cursorBlinkOn3 = false;  
  228.             }  
  229.             else if(editor.equals("regist_passwd_re"))  
  230.             {  
  231.                 cursorBlinkOn1 = false;  
  232.                 cursorBlinkOn2 = false;  
  233.                 cursorBlinkOn3 =! cursorBlinkOn3;  
  234.             }  
  235.             lastCaretBlink = currentTime;  
  236.         }  
  237.     }  
  238.  
  239.     public void run()  
  240.     {  
  241.         //System.out.println("run");  
  242.         while(true)  
  243.         {  
  244.             checkTimeStamp();  
  245.               
  246.             redraw();  
  247.             try   
  248.             {  
  249.                 synchronized(this)  
  250.                 {  
  251.                     //System.out.println("3");  
  252.                     wait(50L);  
  253.                 }             
  254.             }  
  255.             catch(Exception e)  
  256.             {  
  257.                 e.printStackTrace();  
  258.             }  
  259.               
  260.         }  
  261.     }  
  262.  
  263.     protected void keyPressed(int keyCode)  
  264.     {  
  265.         switch(keyCode)  
  266.         {  
  267.             case KeyID.SOFT_RIGHT:  
  268.             {  
  269.                 controller.handleEvent(UIController.EventID.EVENT_EXIT,null);  
  270.                 break;  
  271.             }  
  272.             case KeyID.SOFT_LEFT:  
  273.             {  
  274.                 if(username!="" && passwd!=""&&passwd_re!="")  
  275.                 {  
  276.                     if(passwd.equals(passwd_re))  
  277.                     {  
  278.                           
  279.                           
  280.                         userRecord.db_deleteAllRecord();  
  281.                         if(userRecord.db_getRecord(1)==null)  
  282.                         {  
  283.                             UserDataItem userItem = new UserDataItem(1,(username+","+passwd).getBytes());  
  284.                             userRecord.db_addRecord(userItem);  
  285.                             userItem = null;  
  286.                             System.gc();  
  287.                         }  
  288.                           
  289.                         String update = "start";  
  290.                         Object [] args = {"activeScreen"null, update};  
  291.                         controller.handleEvent(UIController.EventID.EVENT_NEXT_ACTIVE_SCREEN,args);  
  292.                     }  
  293.                 }  
  294.                 break;  
  295.             }  
  296.             case KeyID.KEY_EDIT:  
  297.             case KEY_NUM0:  
  298.             case KEY_NUM1:  
  299.             case KEY_NUM2:  
  300.             case KEY_NUM3:  
  301.             case KEY_NUM4:  
  302.             case KEY_NUM5:  
  303.             case KEY_NUM6:  
  304.             case KEY_NUM7:  
  305.             case KEY_NUM8:  
  306.             case KEY_NUM9:  
  307.             {  
  308.                 //System.out.println(editor);  
  309.                 Object[] args = {object_name,editor,username,passwd,passwd_re};  
  310.                 controller.handleEvent(UIController.EventID.EVENT_USER_REGIST_EDIT,args);  
  311.                 break;  
  312.             }  
  313.             default:;  
  314.         }  
  315.               
  316.         keyCode = getGameAction(keyCode);  
  317.         switch(keyCode)  
  318.         {  
  319.             case UP:  
  320.             case LEFT:  
  321.             {  
  322.                 currentlySelectedIndex--;  
  323.                 if(currentlySelectedIndex<0)  
  324.                 {  
  325.                     currentlySelectedIndex=0;  
  326.                 }  
  327.                 else 
  328.                 {  
  329.                     redraw();  
  330.                 }  
  331.                 break;  
  332.             }  
  333.             case DOWN:  
  334.             case RIGHT:  
  335.             {  
  336.                 currentlySelectedIndex++;  
  337.                 if(currentlySelectedIndex>2)  
  338.                 {  
  339.                     currentlySelectedIndex=2;  
  340.                 }  
  341.                 else 
  342.                 {  
  343.                     redraw();  
  344.                 }  
  345.                   
  346.                 break;  
  347.             }  
  348.         }  
  349.     }  
  350.  
  351. }  
  352.  

*TextEdit是利用GameCanvas绘制的自定义文本编辑框。后续文章将给出具体实现。

#p#

【分析】

1 在MainMidlet调用控制器UIController,并向UIController传递midlet作为参数。

  1. controller=new UIController(<span style="color:#ff0000;">this</span>);  
  2. try {  
  3.     controller.init();  
  4.     } catch (IOException e) {  
  5.     // TODO Auto-generated catch block  
  6.     e.printStackTrace();  
  7.     }// 

2 控制器的实现是通过一个事件的机制实现的, 在UIController中,先建立一个事件ID的内部类。

  1. public static class EventID{  
  2.         private EventID(){  
  3.         }  
  4.           
  5.         public static final byte EVENT_EXIT = 0;//退出  
  6.         public static final byte EVENT_NEXT_WELCOME_SCREEN = 1;//欢迎界面  
  7.         public static final byte EVENT_NEXT_USER_REGIST_SCREEN = 2;//用户注册  
  8.         public static final byte EVENT_USER_REGIST_EDIT = 3;//用户注册编辑  
  9.         public static final byte EVENT_USER_REGIST_EDIT_BACK = 4;//用户注册编辑返回  
  10.         public static final byte EVENT_NEXT_ACTIVE_SCREEN = 5;  
  11.        //...  
  12.     } 

3 一次性初始化所有界面,分配内存,调用时,只是执行视图类的show方法。为什么不将初始话放在调用时进行呢?主要是因为视图类有多次重用,如果每一次调用都new(初始化,分配内存)一次,手机有限的内存很快会被用光,这是会出现一些程序自动退出的问题。

  1. private void initObject()  
  2. {  
  3.     welcomeScreen = new WelcomeScreen(this);  
  4.     reg= new UserRegist(this);  
  5.     activeScreen = new ActiveScreen(this);  
  6.     ...  
  7.     textBox = new PopUpTextBox(this,"输入文本",""1000, TextField.ANY);  

4 控制器对视图的处理采用状态机实现

  1. public void handleEvent( int eventID, Object[] args)  
  2.    {  
  3.     switch (eventID)  
  4.        {     
  5.         case EventID.EVENT_EXIT:  
  6.         {  
  7.             midlet.exit(false);  
  8.             break;  
  9.         }  
  10.         case EventID.EVENT_NEXT_WELCOME_SCREEN:  
  11.         {  
  12.                 welcomeScreen.show();  
  13.             midlet.setCurrent(welcomeScreen);  
  14.             break;  
  15.         }  
  16.         case EventID.EVENT_NEXT_USER_REGIST_SCREEN:  
  17.         case EventID.EVENT_USER_REGIST_EDIT_BACK:  
  18.         {  
  19.             reg.show(args);  
  20.             Thread thread = new Thread(reg);  
  21.             thread.start();  
  22.             midlet.setCurrent(reg);  
  23.             break;  
  24.         }  
  25.         case EventID.EVENT_USER_REGIST_EDIT:  
  26.         {  
  27.             textBox.init(args);  
  28.             midlet.setCurrent(textBox);  
  29.             break;  
  30.         }  
  31.         case EventID.EVENT_NEXT_ACTIVE_SCREEN:  
  32.         {  
  33.             activeScreen.show(args);  
  34.             Thread thread = new Thread(activeScreen);  
  35.             thread.start();  
  36.             midlet.setCurrent(activeScreen);  
  37.             break;  
  38.         }  
  39.         //...  
  40.             default:  
  41.                 break;  
  42.        }  
  43.    }  
  44.  

5 视图类初始化时,需要将控制器作为参数初始化,以对事件做出判断。如WelcomeScreen.java中先做出如下声明:

  1. private UIController controller; 

再在构造函数中,传递控制器

  1. public WelcomeScreen(UIController control) {  
  2.         // TODO Auto-generated constructor stub  
  3.         super(false);  
  4.         controller=control; 

6 视图切换事件响应采用如下方式,在keyPressed中,对按键事件进行判断,然后调用UIController的handEvent方法。

  1. protected void keyPressed(int keycode)  
  2.     {  
  3.         switch(keycode)  
  4.         {  
  5.             case KeyID.SOFT_RIGHT:  
  6.             {  
  7.                 controller.handleEvent(UIController.EventID.EVENT_EXIT,null);  
  8.                 break;  
  9.             }  
  10.             case KeyID.SOFT_LEFT:  
  11.             {  
  12.                 String editor = "regist_name";  
  13.                 Object [] args = {"registScreen",editor, null,null,null};  
  14.                 controller.handleEvent(UIController.EventID.EVENT_NEXT_USER_REGIST_SCREEN,args);  
  15.                 break;  
  16.             }  
  17.             default:;  
  18.         }  
  19.     }  
  20.       

7 控制器可以通过handEvent的args传递参数,如

  1. String update = "start";  
  2. Object [] args = {"activeScreen"null, update};  
  3. controller.handleEvent(UIController.EventID.EVENT_NEXT_ACTIVE_SCREEN,args); 

UserRegist传递了一个update变量给下一个视图。

8 在看一下模型,在UserDataItem中存储的是用户注册的信息。利用UserDataRecord类对记录进行操作。

在视图类中,通过以下方式调用:

先声明

  1. private UserDataRecord userRecord; 

构建对象

  1. userRecord = new UserDataRecord(); 

使用对象

  1. userRecord.db_deleteAllRecord();  
  2.                         if(userRecord.db_getRecord(1)==null)  
  3.                         {  
  4.                             UserDataItem userItem = new UserDataItem(1,(username+","+passwd).getBytes());  
  5.                             userRecord.db_addRecord(userItem);  
  6.                             userItem = null;  
  7.                             System.gc();  
  8.                         }  
  9.                          

9 包com.token.view.components是对视图类中使用的自定义控件的封装

综述,这样就实现了模型、视图、控制的分离。

【参考文献】

(1) 万辉,王军[M]. 基于Eclipse环境的J2ME应用程序开发,清华大学出版社

(2) http://blog.csdn.net/cjjky/article/category/807008

原文链接:http://blog.csdn.net/tandesir/article/details/7538817

【系列文章】

  1. JavaMe开发:低级界面绘图之点阵字
  2. JavaMe开发:低级界面绘图之菜单
  3. JavaMe开发:也说MVC设计模式
  4. JavaMe开发:绘制可自动换行文本
  5. JavaMe开发:绘制文本框TextEdit
  6. JavaM开发:自适应滚动显示
责任编辑:林师授 来源: tandesir的博客
相关推荐

2014-04-14 05:31:08

WindowsPhonWP8MVC

2012-05-09 10:35:36

JavaMEJava

2011-06-02 18:02:50

iPhone MVC

2009-07-10 16:14:29

MVC设计模式Swing

2012-05-09 10:58:25

JavaMEJava

2012-05-09 10:03:08

JavaMEJava

2009-07-30 13:45:40

ASP.NET开发模式MVC模式

2012-05-09 10:22:44

JavaMEJava

2012-05-09 09:49:54

JavaMeJava

2011-04-22 09:26:57

MVC设计

2022-10-30 17:32:25

设计模式单例模式

2010-06-03 14:01:26

JavaSEJavaMEiPhone

2023-08-04 07:26:55

工厂类集中化设计模式

2023-08-07 06:30:15

抽象工厂模式软件设计模式

2023-08-03 08:01:27

单例模式结构开发

2023-08-08 20:13:36

设计模式原型模式

2012-12-18 10:03:22

JavaScriptWebJS

2012-05-28 13:56:41

Web

2023-08-15 11:07:37

适配器模式TypeScript

2023-08-05 13:31:20

工厂方法模式对象
点赞
收藏

51CTO技术栈公众号