服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

java手机软件图形界面api之低级gui组件

     在高级api编程时,你不能控制显示在屏幕上的内容,甚至用编程方式几乎无法控制这些组件。由系统实现体负责选取设备的最佳显示方式。然而,一些如游戏类的应用程序可能需要对屏幕绘制有更多的控制。midp javax.microedition.lcdui包也提供了处理这类编程的低级api。

  为了在屏幕直接绘制直线,文本和形状,你必须使用canvas类。该类提供了一个midlet可以在其上绘制的空白屏幕。例如,在屏幕上绘制字符串"helloworld"。实现这个功能有一个简单的办法:子类化canvas类(它是继承自displayable的一个抽象类)并重载paint()方法。详见代码段1。

  paint()方法的实现使用了javax.microedition.lcdui.graphics类的绘图功能。在方法paint()中,绘图颜色置为红色,然后用红色画一个长方形。其中,方法getwidth( )和getheight( )分别返回canvas对象的宽度和高度。接下来setcolor( )方法把绘图颜色设置为白色;之后,字符串"hello world!"绘制在屏幕的左上角。

  示例1:子类化canvas

import javax.microedition.lcdui.*;
public class mycanvas extends canvas {
 public void paint(graphics g) {
  g.setcolor(255, 0, 0);
  g.fillrect(0, 0, getwidth(), getheight( ));
  g.setcolor(255, 255, 255);
  g.drawstring("hello world!", 0, 0, g.top | g.left);
 }
}

  现在,为了观看mycanvas,必须要把实例化后进行显示。既然canvas是displayable的一个子类,可以用与其它screen 类使用的同样的setcurrent( )方法来显示它。详见代码段2。

  示例2:实例化和显示mycanvas

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class mymidlet extends midlet {
 public mymidlet( ) {}
 public void startapp( ) {
  canvas canvas = new mycanvas( );
  display display = display.getdisplay(this);
  display.setcurrent(canvas);
 }
 public void pauseapp( ) {}
 public void destroyapp(boolean unconditional) {}
}

  如果你在无线开发包提供的模拟器中运行,可能得到如图1所示的效果。注意在代码段5-1中,颜色被设置为红色与白色,但是既然使用了灰度级屏幕,这里的彩色就被映射到黑色和白色的不同的灰度级上。试着调整显示来观察哪一种设备的色彩显示更好些。

java手机软件图形界面api之低级gui组件(图一)
图1.在canvas上绘制"hello world!"
  

    1. 绘图

  坐标(0,0)代表了显示屏的左上角。x坐标的值是从左向右递增的,y坐标的值是从顶向下递增的。应用程序应该一直检查绘图区的大小,这可以通过如下的类canvas提供的方法实现:

public int getheight( );
public int getwidth( );

  这两个方法分别以像素值返回可显示区的高度和宽度。

  所用的绘图模型是像素替换法--用在graphics对象中指定的当前像素值来代替目标像素值。一个24位的色彩模型由红,绿,蓝各8位(rgb)来提供。然而,由于并非所有的设备都支持彩色,应用程序中要求的颜色将被映射到设备中可用的颜色值上。但是,一个良好的应用程序,应该检查一个设备是否支持彩色-这可以用display类的方法iscolor()和numcolors( )来完成。

  graphics类提供了方法setcolor()和getcolor( )来设置和取得颜色。但是,不象awt/swing,不存在方法setbackground( )和setforeground(),所以你必须显式地调用fillrect( )(见示例5-1)。graphics类的大多数的另外一些方法是自解释的,与该类的awt版本中的方法差不多。但是,我们还是要仔细地看一下其中的几个在环境j2me下是如何工作的。

  2. 双缓冲

  双缓冲机制经常用来实现动画的平滑显示效果。在这种技术中,你不是在显示屏上绘图,而是绘制到显示屏的一个拷贝上(一个脱屏的缓冲区)-它是内存的一部分。当缓冲区绘制结束,你就可以把缓冲区内容拷贝到显示屏上。这里的基本原理是,直接拷贝内存内容到显示屏上要快于用原型绘制的速度。

  要实现双缓冲,可以先生成一个其尺寸与屏幕一样的易变图像:

int width = getwidth( );
int height = getheight( );
image buffer = image.createimage(width, height);

  然后,取得缓冲区的图形上下文:

graphics gc = buffer.getgraphics( );
  现在,你可以在缓冲区中绘图了:

// animate
// ..
gc.drawrect(20, 20, 25, 30);

  当需要把缓冲区拷贝到屏幕上时,你可以重载方法paint( )来把缓冲区内容绘制到设备显示屏上:

public void paint(graphics g) {
 g.drawimage(buffer, 0, 0, 0);
}

  注意,一些midp实现中已经采用了双缓冲机制,因此这里的工作可能是不必要的。你可以使用canvas的isdoublebuffered( )方法来检查是否图形是双缓冲方式实现的。

      3. 线程问题

  midp gui api是线程安全的。即是说,gui api方法可以在任何时候从任何线程中调用。唯一的例外是canvas类的servicerepaints( )方法,它立即调用了paint( )方法以强迫显示的立即重绘。这是说,如果paint( )方法想在任何的应用程序调用servicerepaints( )时已锁定的对象上同步,应用程序将会产生死锁。为了避免死锁,在使用了servicerepaints( )方法时,请不要锁定将被paint()方法使用的对象。
另外,在所有未执行的重绘满足后,你可以使用display类的方法callserially( )来执行代码,如下所示:

class testcanvas extends canvas implements runnable {
 void dosomething( ) {
  //代码段1
  callserially(this);
 }
 public void run( ) {
  //代码段2
 }
}

  在此,对象的run( )方法在初始化结束后被调用。

  4. 字体

  应用程序不能自己产生字体。代之的是,应用程序应该要求基于一些属性(如大小,字体名称,字形)的一种字体,底层系统将试着返回一种与要求的字体最相近的字体。font 类用来描述各种字体和尺寸。在font 类中一共定义了三种字体属性,每一种属性取值不同,如下:

属性取值
facemonospace, proportional, system
sizesmall, medium, large
style bold, italic, plain, underlined

  例如,要指定一种中等大小的字体,可以使用font.size_medium;用font.style_italic来指定倾斜字形,等等。字形属性值可以用or(|)操作符结合;另外一些属性值不能结合。例如:下面这种属性值指定了一种常规,带下划线的字体:

style_plain | style_underlined
  而,下面是非法的组合:

size_small | size_medium
  下面也是非法的:

face_system | face_monospace
  系统中的每种字体实际上都是分别实现的,所以为了取得描述字体的对象,可以用getfont( )方法--该方法有三个参数,分别对应字体的字面,大小和字形。如,下面的代码以指定的字面,大小和字形属性得到一个font对象:

font font = font.getfont(face_system,style_plain, size_medium);
  如果没有相匹配的字体,系统将尽可能提供最相近的匹配-总是一个有效的字体对象。

  一旦得到一种字体,你就可以使用font类的方法来检索这种字体的信息。如,你可以用getface(),getsize( )和getstyle( )方法来分别检索该字体的字面,大小和字形信息。

  让我们再看一个例子:示例3中代码子类化canvas 类。在此,绘图颜色设置为白色,并用该色画出一个矩形,然后把绘图色置为黑色。代码剩下的部分在设备屏幕上绘制系统字体,如图2所示。

java手机软件图形界面api之低级gui组件(图二)
图2.在设备显示屏上画出系统字体
  

   示例3:使用字体

import javax.microedition.lcdui.*;
public class fontcanvas extends canvas {
 public void paint(graphics g) {
  g.setcolor(0xffffff);
  g.fillrect(0, 0, getwidth(), getheight( ));
  g.setcolor(0x000000);
  g.setfont(font.getfont(font.face_system, font.style_plain,font.size_large));
  g.drawstring("system font", 0, 0, g.left | g.top);
  g.setfont(font.getfont(font.face_system, font.style_plain,font.size_medium));
  g.drawstring("medium size", 0, 15, g.left | g.top);
  g.setfont(font.getfont(font.face_system, font.style_bold,font.size_medium));
  g.drawstring("bold style", 0, 30, g.left | g.top);
  g.setfont(font.getfont(font.face_system, font.style_italic,font.size_medium));
  g.drawstring("italic style", 0, 45, g.left | g.top);
  g.setfont(font.getfont(font.face_system,font.style_underlined, font.size_medium));
  g.drawstring("underlined style", 0, 60, g.left | g.top);
 }
}

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class fontmidlet extends midlet {
 public fontmidlet( ) {}
 public void startapp( ) {
  canvas canvas = new fontcanvas( );
  display display = display.getdisplay(this);
  display.setcurrent(canvas);
 }
 public void pauseapp( ) {}
 public void destroyapp(boolean unconditional) {}
}

扫描关注微信公众号