【问题描述】在JavaMe连载(3)-也说MVC设计模式 一文中提到了一个TextEdit类,但没有给出具体实现,TextEdit是采用GameCanvas绘制的文本编辑器。本文结合实例给出实现的方法。
【原理】
1 运用Graphics、GameCanvas绘制文本框和光标。
2 检测到输入事件时,跳转到 高级界面->TextBox 。通过系统调用输入法完成输入。
3 将TextBox输入的值返回给TextEdit对象。
【设计模式】
这个过程有点类似装饰模式,实际上,实现输入的还是TextBox,只是给TextBox装饰了一下,形成了一个漂亮的外观。
【代码清单】
TextEdit.java
packagecom.token.view.components;
importjavax.microedition.lcdui.Font;
importjavax.microedition.lcdui.Graphics;
importjavax.microedition.lcdui.game.GameCanvas;
publicclassTextEditextendsGameCanvas
{
privateFont ft;
publicintwidth;
publicintheight;
publicTextEdit(GameCanvas canvas)
{
super(false);
}
//绘制文本框
publicvoiddrawTextBox(GameCanvas canvas, Graphics graphics, String text,intx,inty,booleancursorBlinkOn)
{
//System.out.println("draw");
intpadding =4;
intmargin =2;
ft = Font.getFont(Font.FACE_PROPORTIONAL,Font.STYLE_PLAIN,Font.SIZE_MEDIUM);
graphics.setFont(ft);
width =3*canvas.getWidth()/5+2*padding;
height = ft.getHeight()+2*padding;
graphics.setColor(Color.frame);
graphics.fillRect(x+1,y+1,width+margin,height+margin);
graphics.setColor(Color.frameBg);
graphics.drawRect(x, y,width, height);
graphics.setColor(Color.background);
graphics.fillRect(x+1, y+1,width-1,height-1);
graphics.setColor(Color.text);
graphics.drawString(text, x+padding, y+padding, Graphics.TOP|Graphics.LEFT);
drawCursor(graphics, x+ft.stringWidth(text)+padding, y+padding,1, ft.getHeight(), cursorBlinkOn);
canvas.flushGraphics(x,y,width,height);
}
//绘制光标
publicvoiddrawCursor(Graphics graphics,intx,inty,intwidth,intheight,booleancursorBlinkOn)
{
if(cursorBlinkOn)
{
ft = Font.getFont(Font.FACE_PROPORTIONAL,Font.STYLE_PLAIN,Font.SIZE_MEDIUM);
graphics.setFont(ft);
graphics.setColor(0x0,0x0,0x0);
graphics.drawLine(x+width,y,x+width,y+height);
}
}
}
PopUpTextBox.java
packagecom.token.view;
importjavax.microedition.lcdui.Command;
importjavax.microedition.lcdui.CommandListener;
importjavax.microedition.lcdui.Displayable;
importjavax.microedition.lcdui.TextBox;
importcom.token.util.UIController;
publicclassPopUpTextBoxextendsTextBox {
privateUIController controller;
protectedString canvasText ="";
privateCommand okCommand;
privateCommand cancelCommand;
privateString object_name =null;
privateString editor =null;
privateObject args_t[];
privateObject[] args;
publicPopUpTextBox(UIController control, String title, String text,intmaxsize,intconstraints)
{
super(title, text, maxsize, constraints);
controller = control;
args =newObject[6];
okCommand =newCommand("确定", Command.OK,1);
cancelCommand =newCommand("取消", Command.CANCEL,1);
this.addCommand(okCommand);
this.addCommand(cancelCommand);
this.setCommandListener(newTextBoxListener());
}
publicvoidinit(Object[] args)
{
object_name = ((String)args[0]!=null)?(String)args[0]:"";
editor = ((String)args[1]!=null)?(String)args[1]:"";
//System.out.println(object_name);
//System.out.println(editor);
args_t = args;
this.setString("");
}
protectedvoidcloseTextBox(booleanupdate) {
if(update) canvasText =this.getString();
//System.out.println(canvasText);
if(object_name.equals("registScreen"))
{
if(editor.equals("regist_name"))
{
if(args_t[3]!=""||args_t[3]!=null||args_t[4]!=""||args_t[4]!=null)
{
args[0] = object_name;
args[1] = editor;
args[2] =this.canvasText;
args[3] = args_t[3];
args[4] = args_t[4];
}
controller.handleEvent(UIController.EventID.EVENT_USER_REGIST_EDIT_BACK,args);
}
elseif(editor.equals("regist_passwd"))
{
if(args_t[2]!=""||args_t[2]!=null||args_t[4]!=""||args_t[4]!=null)
{
args[0] = object_name;
args[1] = editor;
args[2] = args_t[2];
args[3] =this.canvasText;
args[4] = args_t[4];
}
controller.handleEvent(UIController.EventID.EVENT_USER_REGIST_EDIT_BACK,args);
}
elseif(editor.equals("regist_passwd_re"))
{
if(args_t[2]!=""||args_t[2]!=null||args_t[3]!=""||args_t[3]!=null)
{
args[0] = object_name;
args[1] = editor;
args[2] = args_t[2];
args[3] = args_t[3];
args[4] =this.canvasText;
}
controller.handleEvent(UIController.EventID.EVENT_USER_REGIST_EDIT_BACK,args);
}
}
//...
}
privateclassTextBoxListenerimplementsCommandListener
{
publicvoidcommandAction(Command command, Displayable disp)
{
if(command==okCommand)
{
closeTextBox(true);
}
elseif(command==cancelCommand)
{
closeTextBox(false);
}
}
}
}
UserRegist.java
packagecom.token.view;
importjavax.microedition.lcdui.Font;
importjavax.microedition.lcdui.Graphics;
importjavax.microedition.lcdui.game.GameCanvas;
importcom.token.model.*;
importcom.token.util.*;
importcom.token.view.components.*;
publicclassUserRegistextendsGameCanvasimplementsRunnable {
privateUIController controller;
privateGraphics graphics;
privateFont ft;
privateMenu menu;
privateHead head;
privateBackGroud backGroud;
privateUserDataRecord userRecord;
privateString title;
privateTextEdit textEdit_name;
privateTextEdit textEdit_passwd;
privateTextEdit textEdit_passwd_re;
privateinttextEdit_name_x;
privateinttextEdit_name_y;
privateinttextEdit_passwd_x;
privateinttextEdit_passwd_y;
privateinttextEdit_passwd_re_x;
privateinttextEdit_passwd_re_y;
privateintcurrentlySelectedIndex =0;
privateString username;
privateString passwd;
privateString passwd_re;
longcaretBlinkDelay = 500L;
longlastCaretBlink =0;
privateString object_name;
privateString editor;
privatebooleancursorBlinkOn1;
privatebooleancursorBlinkOn2;
privatebooleancursorBlinkOn3;
privateintwidth;
privateintheight;
publicUserRegist(UIController control)
{
super(false);
this.controller=control;
this.title ="用户注册";
setFullScreenMode(true);
graphics = getGraphics();
width = getWidth();
height = getHeight();
menu =newMenu(this);
head =newHead(this);
backGroud =newBackGroud(this);
userRecord =newUserDataRecord();
textEdit_name =newTextEdit(this);
textEdit_passwd =newTextEdit(this);
textEdit_passwd_re =newTextEdit(this);
}
publicvoidshow(Object[] args) {
// TODO Auto-generated method stub
setFullScreenMode(true);
object_name = ((String)args[0]!=null)?(String)args[0]:"";
editor = ((String)args[1]!=null)?(String)args[1]:"";
username = ((String)args[2]!=null)?(String)args[2]:"";
passwd = ((String)args[3]!=null)?(String)args[3]:"";
passwd_re = ((String)args[4]!=null)?(String)args[4]:"";
if(editor.equals("regist_name"))
{
cursorBlinkOn1 =true;
cursorBlinkOn2 =false;
cursorBlinkOn3 =false;
currentlySelectedIndex =0;
}
elseif(editor.equals("regist_passwd"))
{
cursorBlinkOn1 =false;
cursorBlinkOn2 =true;
cursorBlinkOn3 =false;
currentlySelectedIndex =1;
}
elseif(editor.equals("regist_passwd_re"))
{
cursorBlinkOn1 =false;
cursorBlinkOn2 =false;
cursorBlinkOn3 =true;
currentlySelectedIndex =2;
}
//System.out.println(object_name);
//System.out.println(editor);
draw();
redraw();
}
publicvoiddraw()
{
//clearScreen();
backGroud.drawBackGroud(this, graphics);
head.drawHead(this,graphics,this.title);
menu.drawMenu(this,graphics,"下一步","退出");
drawBody();
}
privatevoidredraw()
{
switch(currentlySelectedIndex)
{
case0:
{
cursorBlinkOn2 =false;
cursorBlinkOn3 =false;
editor ="regist_name";
break;
}
case1:
{
cursorBlinkOn1 =false;
cursorBlinkOn3 =false;
editor ="regist_passwd";
break;
}
case2:
{
cursorBlinkOn1 =false;
cursorBlinkOn2 =false;
editor ="regist_passwd_re";
break;
}
default:;
}
textEdit_name.drawTextBox(this, graphics, username, textEdit_name_x, textEdit_name_y, cursorBlinkOn1);
textEdit_passwd.drawTextBox(this, graphics, passwd, textEdit_passwd_x, textEdit_passwd_y, cursorBlinkOn2);
textEdit_passwd.drawTextBox(this, graphics, passwd_re, textEdit_passwd_re_x, textEdit_passwd_re_y, cursorBlinkOn3);
textEdit_name.flushGraphics();
}
publicvoiddrawBody()
{
intmargin =5;
ft = Font.getFont(Font.FACE_PROPORTIONAL,Font.STYLE_BOLD,Font.SIZE_LARGE);
String info ="用户名:\n";
String info_wrap1[] = StringDealMethod.format(info, width-10, ft);
graphics.setFont(ft);
graphics.setColor(Color.text);
for(inti=0; i
{
graphics.drawString(info_wrap1[i],5, (i) * ft.getHeight()+40, Graphics.TOP|Graphics.LEFT);
}
textEdit_name_x =5;
textEdit_name_y = info_wrap1.length * ft.getHeight()+40;
textEdit_name.drawTextBox(this, graphics, username, textEdit_name_x, textEdit_name_y, cursorBlinkOn1);
info ="用户密码:\n";
String info_wrap2[] = StringDealMethod.format(info, width-10, ft);
graphics.setFont(ft);
graphics.setColor(Color.text);
for(inti=0; i
{
graphics.drawString(info_wrap2[i],5, (i+info_wrap1.length) * ft.getHeight()+textEdit_name.height+margin+40, Graphics.TOP|Graphics.LEFT);
}
textEdit_passwd_x =5;
textEdit_passwd_y = (info_wrap1.length+info_wrap2.length) * ft.getHeight()+textEdit_name.height+margin+40;
textEdit_passwd.drawTextBox(this, graphics, passwd, textEdit_passwd_x, textEdit_passwd_y, cursorBlinkOn2);
info ="密码确认:\n";
String info_wrap3[] = StringDealMethod.format(info, width-10, ft);
graphics.setFont(ft);
graphics.setColor(Color.text);
for(inti=0; i
{
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);
}
textEdit_passwd_re_x =5;
textEdit_passwd_re_y = (info_wrap1.length+info_wrap2.length+info_wrap3.length) * ft.getHeight()+textEdit_name.height+textEdit_passwd.height+2*margin+40;
textEdit_passwd_re.drawTextBox(this, graphics, passwd_re, textEdit_passwd_re_x, textEdit_passwd_re_y, cursorBlinkOn3);
}
publicvoidclearScreen()
{
graphics.setColor(0xff,0xff,0xff);
graphics.fillRect(0,0, width, height);
}
publicvoidcheckTimeStamp()
{
longcurrentTime = System.currentTimeMillis();
//System.out.println("1");
if(lastCaretBlink + caretBlinkDelay
{
//System.out.println("2");
if(editor.equals("regist_name"))
{
cursorBlinkOn1 =! cursorBlinkOn1;
cursorBlinkOn2 =false;
cursorBlinkOn3 =false;
}
elseif(editor.equals("regist_passwd"))
{
cursorBlinkOn1 =false;
cursorBlinkOn2 =! cursorBlinkOn2;
cursorBlinkOn3 =false;
}
elseif(editor.equals("regist_passwd_re"))
{
cursorBlinkOn1 =false;
cursorBlinkOn2 =false;
cursorBlinkOn3 =! cursorBlinkOn3;
}
lastCaretBlink = currentTime;
}
}
publicvoidrun()
{
//System.out.println("run");
while(true)
{
checkTimeStamp();
redraw();
try
{
synchronized(this)
{
//System.out.println("3");
wait(50L);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
protectedvoidkeyPressed(intkeyCode)
{
switch(keyCode)
{
caseKeyID.SOFT_RIGHT:
{
controller.handleEvent(UIController.EventID.EVENT_EXIT,null);
break;
}
caseKeyID.SOFT_LEFT:
{
if(username!=""&& passwd!=""&&passwd_re!="")
{
if(passwd.equals(passwd_re))
{
userRecord.db_deleteAllRecord();
if(userRecord.db_getRecord(1)==null)
{
UserDataItem userItem =newUserDataItem(1,(username+","+passwd).getBytes());
userRecord.db_addRecord(userItem);
userItem =null;
System.gc();
}
String update ="start";
Object [] args = {"activeScreen",null, update};
controller.handleEvent(UIController.EventID.EVENT_NEXT_ACTIVE_TOKEN_SCREEN,args);
}
}
break;
}
caseKeyID.KEY_EDIT:
caseKEY_NUM0:
caseKEY_NUM1:
caseKEY_NUM2:
caseKEY_NUM3:
caseKEY_NUM4:
caseKEY_NUM5:
caseKEY_NUM6:
caseKEY_NUM7:
caseKEY_NUM8:
caseKEY_NUM9:
{
//System.out.println(editor);
Object[] args = {object_name,editor,username,passwd,passwd_re};
controller.handleEvent(UIController.EventID.EVENT_USER_REGIST_EDIT,args);
break;
}
default:;
}
keyCode = getGameAction(keyCode);
switch(keyCode)
{
caseUP:
caseLEFT:
{
currentlySelectedIndex--;
if(currentlySelectedIndex<0)
{
currentlySelectedIndex=0;
}
else
{
redraw();
}
break;
}
caseDOWN:
caseRIGHT:
{
currentlySelectedIndex++;
if(currentlySelectedIndex>2)
{
currentlySelectedIndex=2;
}
else
{
redraw();
}
break;
}
}
}
}
【分析】
1 文本框的绘制(TextEdit.java)
需要传递GameCanvas、Graphics对象,实现绘图,策略是谁使用,谁传递该参数。此外需要床底文本框左上角坐标(x,y)以及控制光标闪烁的变量cursorBlinkOn。
publicvoiddrawTextBox(GameCanvas canvas, Graphics graphics, String text,intx,inty,booleancursorBlinkOn)
{
//System.out.println("draw");
intpadding =4;
intmargin =2;
ft = Font.getFont(Font.FACE_PROPORTIONAL,Font.STYLE_PLAIN,Font.SIZE_MEDIUM);
graphics.setFont(ft);
width =3*canvas.getWidth()/5+2*padding;
height = ft.getHeight()+2*padding;
graphics.setColor(Color.frame);
graphics.fillRect(x+1,y+1,width+margin,height+margin);
graphics.setColor(Color.frameBg);
graphics.drawRect(x, y,width, height);
graphics.setColor(Color.background);
graphics.fillRect(x+1, y+1,width-1,height-1);
graphics.setColor(Color.text);
graphics.drawString(text, x+padding, y+padding, Graphics.TOP|Graphics.LEFT);
drawCursor(graphics, x+ft.stringWidth(text)+padding, y+padding,1, ft.getHeight(), cursorBlinkOn);
canvas.flushGraphics(x,y,width,height);
}
2 绘制光标(TextEdit.java)
publicvoiddrawCursor(Graphics graphics,intx,inty,intwidth,intheight,booleancursorBlinkOn)
{
if(cursorBlinkOn)
{
ft = Font.getFont(Font.FACE_PROPORTIONAL,Font.STYLE_PLAIN,Font.SIZE_MEDIUM);
graphics.setFont(ft);
graphics.setColor(0x0,0x0,0x0);
graphics.drawLine(x+width,y,x+width,y+height);
}
}
3 实现光标闪烁
光标闪烁的实现需要用到线程,在UIController.java类中,需要绘制文本框的视图类,需要实现线程接口。
UIController.java
caseEventID.EVENT_NEXT_USER_REGIST_SCREEN:
caseEventID.EVENT_USER_REGIST_EDIT_BACK:
{
reg.show(args);
Thread thread =newThread(reg);
thread.start();
midlet.setCurrent(reg);
break;
}
UserRegist.java
publicvoidcheckTimeStamp()
{
longcurrentTime = System.currentTimeMillis();
//System.out.println("1");
if(lastCaretBlink + caretBlinkDelay
{
//System.out.println("2");
if(editor.equals("regist_name"))
{
cursorBlinkOn1 =! cursorBlinkOn1;
cursorBlinkOn2 =false;
cursorBlinkOn3 =false;
}
elseif(editor.equals("regist_passwd"))
{
cursorBlinkOn1 =false;
cursorBlinkOn2 =! cursorBlinkOn2;
cursorBlinkOn3 =false;
}
elseif(editor.equals("regist_passwd_re"))
{
cursorBlinkOn1 =false;
cursorBlinkOn2 =false;
cursorBlinkOn3 =! cursorBlinkOn3;
}
lastCaretBlink = currentTime;
}
}
publicvoidrun()
{
//System.out.println("run");
while(true)
{
checkTimeStamp();
redraw();
try
{
synchronized(this)
{
//System.out.println("3");
wait(50L);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
4 调用高级界面TextBox子类PopUpTextBox
调用时,将调用对象名、编辑对象名、以及编辑框参数传递给PopUpTextBox对象(一定要有,目的是保存编辑框的值,否则多次调用返回时,不同编辑框的值被刷新为空了)
UserRegist.java(KeyPressed)
caseKeyID.KEY_EDIT:
caseKEY_NUM0:
caseKEY_NUM1:
caseKEY_NUM2:
caseKEY_NUM3:
caseKEY_NUM4:
caseKEY_NUM5:
caseKEY_NUM6:
caseKEY_NUM7:
caseKEY_NUM8:
caseKEY_NUM9:
{
//System.out.println(editor);
Object[] args = {object_name,editor,username,passwd,passwd_re};
controller.handleEvent(UIController.EventID.EVENT_USER_REGIST_EDIT,args);
break;
}
UIController.java
caseEventID.EVENT_USER_REGIST_EDIT:
{
textBox.init(args);
midlet.setCurrent(textBox);
break;
}
5 PopUpTextBox参数的接收
publicvoidinit(Object[] args)
{
object_name = ((String)args[0]!=null)?(String)args[0]:"";
editor = ((String)args[1]!=null)?(String)args[1]:"";
//System.out.println(object_name);
//System.out.println(editor);
args_t = args;
this.setString("");
}
6 PopUpTextBox返回输入法输入的值
if(update) canvasText =this.getString();
7 PopUpTextBox输入值处理
依据调用的对象,以及编辑对象,对输入的值进行处理,传递给父对象编辑框
if(object_name.equals("registScreen"))
{
if(editor.equals("regist_name"))
{
if(args_t[3]!=""||args_t[3]!=null||args_t[4]!=""||args_t[4]!=null)
{
args[0] = object_name;
args[1] = editor;
args[2] =this.canvasText;
args[3] = args_t[3];
args[4] = args_t[4];
}
controller.handleEvent(UIController.EventID.EVENT_USER_REGIST_EDIT_BACK,args);
}
elseif(editor.equals("regist_passwd"))
{
if(args_t[2]!=""||args_t[2]!=null||args_t[4]!=""||args_t[4]!=null)
{
args[0] = object_name;
args[1] = editor;
args[2] = args_t[2];
args[3] =this.canvasText;
args[4] = args_t[4];
}
controller.handleEvent(UIController.EventID.EVENT_USER_REGIST_EDIT_BACK,args);
}
elseif(editor.equals("regist_passwd_re"))
{
if(args_t[2]!=""||args_t[2]!=null||args_t[3]!=""||args_t[3]!=null)
{
args[0] = object_name;
args[1] = editor;
args[2] = args_t[2];
args[3] = args_t[3];
args[4] =this.canvasText;
}
controller.handleEvent(UIController.EventID.EVENT_USER_REGIST_EDIT_BACK,args);
}
}
8 输入值的显示
(1) 新建对象
privateTextEdit textEdit_name;
textEdit_name =newTextEdit(this);
(2) 接受输入的参数
object_name = ((String)args[0]!=null)?(String)args[0]:"";
editor = ((String)args[1]!=null)?(String)args[1]:"";
username = ((String)args[2]!=null)?(String)args[2]:"";
passwd = ((String)args[3]!=null)?(String)args[3]:"";
passwd_re = ((String)args[4]!=null)?(String)args[4]:"";
(3) 光标控制,定位到编辑对象,控制编辑对象的光标闪烁(run方法)
privatevoidredraw()
{
switch(currentlySelectedIndex)
{
case0:
{
cursorBlinkOn2 =false;
cursorBlinkOn3 =false;
editor ="regist_name";
break;
}
case1:
{
cursorBlinkOn1 =false;
cursorBlinkOn3 =false;
editor ="regist_passwd";
break;
}
case2:
{
cursorBlinkOn1 =false;
cursorBlinkOn2 =false;
editor ="regist_passwd_re";
break;
}
default:;
}
//...
}
(4) 编辑框的绘制
privatevoidredraw()
{
...
textEdit_name.drawTextBox(this, graphics, username, textEdit_name_x, textEdit_name_y, cursorBlinkOn1);
textEdit_passwd.drawTextBox(this, graphics, passwd, textEdit_passwd_x, textEdit_passwd_y, cursorBlinkOn2);
textEdit_passwd.drawTextBox(this, graphics, passwd_re, textEdit_passwd_re_x, textEdit_passwd_re_y, cursorBlinkOn3);
textEdit_name.flushGraphics();
}
实现的效果如图1所示:
图1 编辑框效果
【参考文献】
【系列文章】
【责任编辑:小林 TEL:(010)68476606】
点赞 0