接下来我们来介绍一下LCDUI这个包及其相关内容,大家都知道,在J2SE里面我们用AWT或者SWING来开发用户界面,但是在J2ME里面,开发用户界面并非上述的AWT或者SWING,我们使用的是全新的针对移动设备设计的LCDUI包(即Limited Configuration Device User Interface)。
在
MIDP
中,和用户界面相关的回调函数有四个:
(1)
javax.microedition.lcdui.Command
类
;
(2)
javax.microedition.lcdui.Canvas
类
(3)
在屏幕重绘时,会产生重绘事件,此时的
Canvas
类的
paint()
方法会被调用,并传入一个
Graphics
对象的调用;
(4)
调用
Display
类的
callSerially
()方法时,会传入一个
Runnable
接口的类,其中的
run()
方法会被调用。
下面我们来介绍一下
javax.microedition.lcdui.Command
这个类,它既适用于高级
API(Screen
类
),
又使用于低级
API(Canvas
类
).
Command
类有两种构造函数,一个有三个参数,另一个则是四个参数。
区别在于:前者第一个参数是显示在画面上名称,第二个参数是命令的类型,第三参数是优先权,以自然数形式表示,如:
1
,
2
,
3…
,越小优先权越高,代表在屏幕显眼的地方显示。而后者则是在前者的基础上增加了一个长命令的参数,具体位于前者第一和第二个参数之间,具体机型上的显示和厂家的实现的不同而不同。
前面介绍的命令的类型共分为
8
种:
Command.BACK
,
ommand.EXIT
,
Command.CANCEL
,
Command.HELP
,
Command.ITEM
,
Command.OK
,
Command.SCREEN
,
Command.STOP
。
例:
Command c=new Command(“
取消
”,Command.CANCEL,1);
Command a=new Command(“
这是长命令
”,”
这是短命令
”,Command.BACK,1);
在屏幕上光显示出这些是没有任何意义的,我们必须还要将
Command
类和
javax.microedition.lcdui.CommandListener
结合起来使用才能反应用户的动作,由于
setCommandListener()
定义于
Displayable
中,所以
CommandListener
是一个和
Command
一样可以通用与高级
API
和低级
API
的事件处理接口。
0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" border=undefined twffan="done">
需要注意的是
CommandListener
采用的是
Unicast
机制,也就是说,同一时刻只能注册一个时间处理函数。
下面是一个在
MIDlet
中使用
Command
和
CommandListener
的大致情形:
public class example1 extends MIDlet implements CommandListener
{
public void startApp()
{
………
Command exp1=new Command(“
命令<chmetcnv w:st="on" unitname="”" sourcevalue="1" hasspace="False" negative="False" numbertype="1" tcsc="0"></chmetcnv>
1”
,Command.OK,1);
………
}
public void pauseApp()
{
………
}
public void destroyApp(boolean exp)
{
………
}
public void commandAction(Command c,Displayable s)
{
………
}
}
介绍完了
Command
类,我们来介绍一下
Ticker
类,在
MIDP1.0
中,它只能用于
Screen
的子类,在
MIDP2.0
后,已经可以用于
Displayable
的所有子类了。它是一个类似于跑马灯的类,即通常所见的进度条,我们通常用
setTicker()
来设定画面上的
Ticker
,或者用
getTicker()
来取得画面上的
Ticker
对象,
setTicker()
中的括号内的双引号中的字符串即显示在跑马灯中的文字。
下面用一个例子来详细介绍一下上面几个类的用法,作为本章的小结。
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class DisplayableTestMIDlet extends MIDlet implements CommandListener
{
public void startApp()
{
display=Display.getDisplay(this);
}
public void pauseApp()
{
f=new Form("Displayable
测试
");
Command test1=new Command("
开始
Ticker",Command.SCREEN,1);
Command test2=new Command("
停止
Ticker",Command.SCREEN,1);
Command test3=new Command("
退出
",Command.EXIT,1);
f.addCommand(test1);
f.addCommand(test2);
f.addCommand(test3);
f.setCommandListener(this);
display.setCurrent(f);
}
public void destroyApp(boolean unconditional)
{
}
public void commandAction(Command c,Displayable s)
{
String cmd=c.getLabel();
if(cmd.equals("
开始
Ticker"))
{
f.setTicker(new Ticker("
运作中
"));
}
if(cmd.equals("
停止
Ticker"))
{
f.setTicker(null);
}
}
private Display display;
Form f;
}
Screen类有四个相关的子类,分别为Alert,List,TextBox,Form,这四个子类可以细分为两类,前三者属于封装了较复杂用户界面的类,我们只能单纯的拿来使用,对于其内部的组成结构无法修改;相对前三者,Form则是自由的多,它是默认缺省没有任何用户界面的组件,它类似于一个容器,可以容纳Item类的子类,以构成复杂的图形用户界面.
下面我们来详细介绍一下这四个子类:
0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" align=middle border=undefined twffan="done">
List组件根据Choice接口中的定义,分为Choice.EXCLUSIVE,Choice.MULTIPLE,Choice.IMPLICIT三种,它们之间的区别也很简单,你只需从字面便可读出区别来,分别为单选类型的,多选类型的,简易式的单选,IMPLICIT和EXCLUSIVE的最大区别在于,Choice.IMLICIT类型的List会在用户选择之后立刻触发时间,并将List.SELECT_COMMAND做为commandAction()函数的第一个参数传入,经由次判别,我们可以知道事件是否由List触发,因为这种类型的List在同一时间只有一个选项会被选择。Choice接口给List提供了一种叫Fit Policy的机制,分别为Choice.TEXT_WRAP_DEFAULT,Choice.TEXT_WRAP_ON,Choice.TEXT_WRAP_OFF三种,它们用来决定过长的文字如何被处理,使用Choice.TEXT_WRAP_ON时,过长的文字会自动编排到下一行,而Choice.TEXT_WRAP_OFF则市自动截断,DEFAULT则是根据厂家默认来选择。
代码示范如下:
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class ImplicitListWithFitPolicyMIDlet extends MIDlet implements CommandListener
{
private Display display;
public ImplicitListWithFitPolicyMIDlet()
{
display=Display.getDisplay(this);
}
public void startApp()
{
Image img=null;
try
{
img=Image.createImage("/A.png");
}catch(Exception e)
{
System.out.println(e);
}
List l=new List("List
测试
",Choice.IMPLICIT);
System.out.println("
缺省的
Fit Policy:"+l.getFitPolicy());
l.append("12345678901234567890",img);
l.append("abcdefgabcdefg",img);
Command c1=new Command("WRAP_OFF",Command.OK,1);
l.addCommand(c1);
Command c2=new Command("WRAP_ON",Command.OK,1);
l.addCommand(c2);
Command c3=new Command("WRAP_DEFAULT",Command.OK,1);
l.addCommand(c3);
l.setCommandListener(this);
display.setCurrent(l);
}
public void commandAction(Command c,Displayable s)
{
String cmd=c.getLabel();
if(cmd.equals("WRAP_OFF"))
{
List tmp=(List) s;
tmp.setFitPolicy(Choice.TEXT_WRAP_OFF);
}
if(cmd.equals("WRAP_ON"))
{
List tmp=(List) s;
tmp.setFitPolicy(Choice.TEXT_WRAP_ON);
}
if(cmd.equals("WRAP_DEFAULT"))
{
List tmp=(List) s;
tmp.setFitPolicy(Choice.TEXT_WRAP_DEFAULT);
}
}
public void pauseApp()
{
}
public void destroyApp(boolean unconditional)
{
}
}
下面我们再来说一说
TextBox
,当用户需要输入文字时,
TextBox
就派上用场了,
TextBox
定义使用如下
:TextBox tb=new TextBox(“
文字输入测试
”,”
名字
”,9
,
TextField.ANY);
其中
’
输入测试
’
是
Title,
而
’
名字
’
则是我们指的内容,第三个参数就是我们要限制的参数
2
的字符数,第四个参数则是对输入内容做了更进一步的限制,
ANY
指的是允许输入任何字符或数字,类似还有
EMAILADDR
则是指允许输入电子邮件地址,等等(参见
API
说明文档)。
下面介绍一下
AlertType
,它是一个工具类,本身是无法实体化的它提供了几种定义好的
AlertType
用以辅助
Alert
类的使用。比如:
ALARM
(警报),
CONFIRMATION
(确定),
ERROR
(错误)等等,
Alert
是一个比较特殊的
Screen
类的对象,当我们利用
Display.setCurrent()
这个方法的时候,它会先发出一段声音,然后将自己显示在屏幕上,过一段时间后,跳回之前的画面,因此,请注意,我们必须要使系统一定要存在一个画面,这样才能让
Alert
条回,否则,会发生错误,下面一段代码提示
Alert
的使用
:
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class AlertSplashScreenMIDlet extends MIDlet
{
private Display display;
public AlertSplashScreenMIDlet()
{
display=Display.getDisplay(this);
}
public void startApp()
{
Alert a1=new Alert(“
应用程序开始启动
”);
a1.setType(AlertType.INFO);
setTimeout(5000);
a1.setString(“
应用程序初始化中,请稍等
”);
Form f=new Form(“
主画面
”);
dsplay.setCurrent(a1,f);
}
public void pauseApp()
{
}
public void destroyApp(boolean unconditional)
{
}
}
至于
Form
,是这个
Screen
类中最终要的一个子类,是高级图形界面中最长用到的,我们留在后面的章节中继续探讨它
~
代码示范如下:
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class ImplicitListWithFitPolicyMIDlet extends MIDlet implements CommandListener
{
private Display display;
public ImplicitListWithFitPolicyMIDlet()
{
display=Display.getDisplay(this);
}
public void startApp()
{
Image img=null;
try
{
img=Image.createImage("/A.png");
}catch(Exception e)
{
System.out.println(e);
}
List l=new List("List
测试
",Choice.IMPLICIT);
System.out.println("
缺省的
Fit Policy:"+l.getFitPolicy());
l.append("12345678901234567890",img);
l.append("abcdefgabcdefg",img);
Command c1=new Command("WRAP_OFF",Command.OK,1);
l.addCommand(c1);
Command c2=new Command("WRAP_ON",Command.OK,1);
l.addCommand(c2);
Command c3=new Command("WRAP_DEFAULT",Command.OK,1);
l.addCommand(c3);
l.setCommandListener(this);
display.setCurrent(l);
}
public void commandAction(Command c,Displayable s)
{
String cmd=c.getLabel();
if(cmd.equals("WRAP_OFF"))
{
List tmp=(List) s;
tmp.setFitPolicy(Choice.TEXT_WRAP_OFF);
}
if(cmd.equals("WRAP_ON"))
{
List tmp=(List) s;
tmp.setFitPolicy(Choice.TEXT_WRAP_ON);
}
if(cmd.equals("WRAP_DEFAULT"))
{
List tmp=(List) s;
tmp.setFitPolicy(Choice.TEXT_WRAP_DEFAULT);
}
}
public void pauseApp()
{
}
public void destroyApp(boolean unconditional)
{
}
}
下面我们再来说一说
TextBox
,当用户需要输入文字时,
TextBox
就派上用场了,
TextBox
定义使用如下
:TextBox tb=new TextBox(“
文字输入测试
”,”
名字
”,9
,
TextField.ANY);
其中
’
输入测试
’
是
Title,
而
’
名字
’
则是我们指的内容,第三个参数就是我们要限制的参数
2
的字符数,第四个参数则是对输入内容做了更进一步的限制,
ANY
指的是允许输入任何字符或数字,类似还有
EMAILADDR
则是指允许输入电子邮件地址,等等(参见
API
说明文档)。
下面介绍一下
AlertType
,它是一个工具类,本身是无法实体化的它提供了几种定义好的
AlertType
用以辅助
Alert
类的使用。比如:
ALARM
(警报),
CONFIRMATION
(确定),
ERROR
(错误)等等,
Alert
是一个比较特殊的
Screen
类的对象,当我们利用
Display.setCurrent()
这个方法的时候,它会先发出一段声音,然后将自己显示在屏幕上,过一段时间后,跳回之前的画面,因此,请注意,我们必须要使系统一定要存在一个画面,这样才能让
Alert
条回,否则,会发生错误,下面一段代码提示
Alert
的使用
:
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class AlertSplashScreenMIDlet extends MIDlet
{
private Display display;
public AlertSplashScreenMIDlet()
{
display=Display.getDisplay(this);
}
public void startApp()
{
Alert a1=new Alert(“
应用程序开始启动
”);
a1.setType(AlertType.INFO);
setTimeout(5000);
a1.setString(“
应用程序初始化中,请稍等
”);
Form f=new Form(“
主画面
”);
dsplay.setCurrent(a1,f);
}
public void pauseApp()
{
}
public void destroyApp(boolean unconditional)
{
}
}
至于
Form
,是这个
Screen
类中最终要的一个子类,是高级图形界面中最长用到的,我们留在后面的章节中继续探讨它
~
当我们选择了Canvas这个类,就意味着我们准备采用低级API,之所以称之为低级API,并不是因为它很低能,恰恰相反,我们可用它来处理一些很底层的系统事件,具体如何支持,我们要看硬件上的支持程度来判定。
下面列出判断硬件支持程度的方法列表:
0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" border=undefined twffan="done">
所有的低级
API
都是从
javax.microedition.lcdui.Canvas
开始,我们必须继承
Canvas
,才可以建立一个显示在屏幕上的画面,需要注意的是每一个
Canvas
里面必须有一个抽象方法
paint(),
并且需要传入一个
Graphics
的引用,可以说
Canvas
的精华就在这个
paint()
方法里面,我们用这个方法来负责这个屏幕画面的描绘。
任何时候我们都可以用
repaint()
来产生重绘事件,
repaint()
一共有两个同名方法,其中一个需要四个参数,分别是起始坐标(
x,y
),还有宽度和高度,另外一个不需要任何参数,它是代表整个屏幕全部重新绘制,由此看来,前者的效率较后者要高,实际开发中也大多数是用前者而不是后者,我们调用了
repaint()
之后,会立刻返回,调用
paint()
则是由另外一个专门处理
UI
的线程来完成,如果我们希望等到
paint()
完成后再返回,我们可以在
repaint()
方法后加一个
serviceRepaints()
方法,它的作用是强制队列中的重绘事件尽快完成,如果队列中无重绘事件,它就什么也不会做,因此调用
repaint()
方法的时候,我们通常会在后面加一个
serviceRepaints()
方法。
我们在手机上绘制图象的坐标系和我们通常所见的坐标系是不一样的
<textbox style="MARGIN-TOP: 4.656pt; LEFT: auto; MARGIN-LEFT: 8.281pt; WIDTH: 29.875pt; TOP: auto; HEIGHT: 23.312pt"></textbox>
<textbox style="MARGIN-TOP: 4.875pt; LEFT: auto; MARGIN-LEFT: 8.281pt; WIDTH: 11.906pt; TOP: auto; HEIGHT: 31.031pt"></textbox>
<textbox style="MARGIN-TOP: 4.843pt; LEFT: auto; MARGIN-LEFT: 8.281pt; WIDTH: 65.906pt; TOP: auto; HEIGHT: 31.062pt"></textbox>
<textbox style="MARGIN-TOP: 5pt; LEFT: auto; MARGIN-LEFT: 8.312pt; WIDTH: 56.875pt; TOP: auto; HEIGHT: 15.468pt"></textbox>
<textbox style="MARGIN-TOP: 4.562pt; LEFT: auto; MARGIN-LEFT: 8.312pt; WIDTH: 2.875pt; TOP: auto; HEIGHT: 54.468pt"></textbox>
<textbox style="MARGIN-TOP: 4.375pt; LEFT: auto; MARGIN-LEFT: 8.312pt; WIDTH: 74.875pt; TOP: auto; HEIGHT: 46.656pt"></textbox>
0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" border=undefined twffan="done">
这是我们在绘制图象时要注意的。
下面我们来讲一讲
Graphics
这个对象,我们可以把它当作一个白纸,只要调用这个方法,我们就可以运用自己的想象力在这张白纸上画出自己想要的图案。
下面我用一段简单的代码来说明一下这个
Graphics
对象的应用:
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class test extends Canvas
{
public void paint(Graphics g)
{
g.setColor(255,255,0);
g.fillRect(0,0,getWidth(),getHeight());
int c=g.getColor();
int dc=g.getDisplayColor(g.getColor());
System.out.println("
当前画面的颜色为:
"+Integer.toHexString(c));
System.out.println("
当前画面的
R
值为:
"+g.getRedComponent());
System.out.println("
当前画面的
G
值为:
"+g.getGreenComponent());
System.out.println("
当前画面的
B
值为:
"+g.getBlueComponent());
System.out.println("
当前画面的显示颜色为:
"+Integer.toHexString(dc));
System.out.println("
当前画面的灰度为:
"+g.getGrayScale());
}
}
需要大家注意的是
R
,
G
,
B
的值只能在
0
——
255
之间,不可以超出这个范围,另外我们可以直接用
0x00RRGGBB
格式进行颜色的调配。
上面的代码简要说了一下
Graphics
几个重要的参数如何获得,下面我们就来谈一谈如何用
Graphics
做具体的图形,如果我们需要绘制一条直线,我们可以调用
drawLine()
方法,需要定义其开始坐标和结束坐标,共四个参数,同时,
Graphics
提供两种形式的线条,一个是虚线,即
Graphics.DOTTED
,一个是实线,即
Graphics.SOLID,
同样我们给出一段代码供大家参考:
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class GraphicsTestCanvas2 extends Canvas
{
public void paint(Graphics g)
{
g.setColor(255,255,255);
g.fillRect(0,0,getWidth(),getHeight());
g.setColor(255,0,0);
g.drawLine(1,1,100,10);
分享到:
评论