技术开发 频道

使用NetBeans进行J2ME开发(三):低级图形用户界面Canvas

  【IT168 技术文档】在这一篇中,我将向大家介绍图形用户界面中的低级图形用户界面。所谓低级图形用户界面,指的是那种我们可以自己在上面画图的控件,它是和TextBox,List等等这些用户控件刚好相对的概念,因为这些用户控件的形状是事先画好的,无需我们程序员操心,所以称为高级图形界面。低级图形用户界面什么东西都需要我们自己画,所以比较复杂,当然也更加灵活,只有想不到,没有画不出,所以我们先介绍它。

  在J2ME开发中,低级图形用户界面是由javax.microedition.lcdui.Canvas类实现的,我们只要继承这个类,并实现这个类的paint方法,就可以随心所欲的进行绘画了。当然,绘画之前,我们少不了要了解我们的手机屏幕究竟有多大的画图空间,这可以通过调用Canvas类的getWidth和getHeight方法实现。下面是一个简短的程序,向大家演示了怎么获画布的大小,同时,也算是一个小小的框架。首先,当然是创建我们自己的画布,代码如下: package com.xkland.j2me;  

  import javax.microedition.lcdui.Canvas;   import javax.microedition.lcdui.Graphics;      /** *//**    *    * @author 海边沫沫    */   public class MyCanvas extends Canvas {       /** *//** Creates a new instance of MyCanvas */    public MyCanvas() {    }      public void clearBackground(Graphics g){    int color = g.getColor();    g.setColor(0xffffff);    g.fillRect(0,0,getWidth(),getHeight());    g.setColor(color);    }      public void paint(Graphics g){    //清除背景    clearBackground(g);      //显示可供绘图的区域的大小    g.drawString("宽度:",10,10,Graphics.LEFT|Graphics.TOP);    g.drawString(String.valueOf(getWidth()),50,10,Graphics.LEFT|Graphics.TOP);    g.drawString("高度:",10,25,Graphics.LEFT|Graphics.TOP);    g.drawString(String.valueOf(getHeight()),50,25,Graphics.LEFT|Graphics.TOP);    }      }

  第二个类当然就是我们的Midlet了,因为它是主程序嘛。在程序启动的时候调用display.setCurrent将画布设置为主界面,同时设置事件监听器。代码比较简单,如下: package com.xkland.j2me;  

  import javax.microedition.midlet.*;   import javax.microedition.lcdui.*;     /** *//**    *    * @author 海边沫沫    * @version    */   public class CanvasTest extends MIDlet{    private Canvas canvas = new MyCanvas();    private Display display = null;    private Command exitCommand = new Command("退出",Command.EXIT,1);      public void startApp() {    if(display==null){    display = Display.getDisplay(this);    canvas.addCommand(exitCommand);    canvas.setCommandListener(new MyCommandListener(this,canvas));    display.setCurrent(canvas);    }    }      public void pauseApp() {    }      public void destroyApp(boolean unconditional) {    }   }

  第三个类当然是我们的事件监听器类了,等一下我们会讲到,Canvas支持许多低级事件,比如键盘的按键事件,所以我们这里把事件监听器单独抽取出来,代码如下: package com.xkland.j2me;  

  import javax.microedition.lcdui.CommandListener;   import javax.microedition.lcdui.Command;   import javax.microedition.lcdui.Displayable;   import javax.microedition.lcdui.Canvas;     /** *//**    *    * @author 海边沫沫    */   public class MyCommandListener implements CommandListener{      private CanvasTest app;    private Canvas canvas;       /** *//** Creates a new instance of MyCommandListener */    public MyCommandListener(CanvasTest app,Canvas canvas) {    this.app = app;    this.canvas = canvas;    }      public void commandAction(Command cmd, Displayable displayable){    if(cmd.getLabel().equalsIgnoreCase("退出")){    app.destroyApp(false);    app.notifyDestroyed();    }    }     }

  下面是运行效果:

  知道了画图区域的大小,同时又知道Canvas可以支持许多低级事件,我们就可以发挥我们自己的想象力创建一个小游戏了。下面,我将写一个简单的拼图游戏,只需要使用上下左右四个方向键操作即可,在事件监听器中,我们只需响应Canvas的keyPressed()事件即可。代码也不复杂,只需把上面的程序稍加扩展即可。当然,我们还需要准备一些图片当素材。

  首先,在网上随便找一张图片,使用图形编辑软件调整图片的大小,然后再裁成3*4共12幅图象。把这12幅图象分别命名为1.png到12.png,同时还要准备一张全白的图片,命名为0.png,这张图片和前面的12张图片一样大小。在项目所在的文件夹下建立一个文件夹,取名为pictures,把这些图片都拷贝进去。在NetBeans IDE左边的文件选项卡中可以看到这些文件,如图:

  但是,在生成项目的时候,这些文件并不会自动打包到项目中,我们必须将这个文件夹捆绑为该项目的资源。在项目上点右键,在弹出的菜单中选择属性,弹出如下对话框,选中左边的“库和资源”,在右边点击“添加文件夹”按钮即可:

  下面是我的MyCanvas类的全部代码,其它两个类的代码没有改变。在这里,我使用的图片是174*280的大小,切割后的小图片每一个都是58*70的大小,空白的图片也是58*70的大小。请看代码:

package com.xkland.j2me;      import javax.microedition.lcdui.Canvas;   import javax.microedition.lcdui.Graphics;   import javax.microedition.lcdui.Image;   import java.util.Random;      /** *//**    *    * @author 海边沫沫    */   public class MyCanvas extends Canvas {    public int[][] pics = new int[4][4];    public Image[] images = new Image[13];    public int step = 0;    public int spaceX = 3;    public int spaceY = 0;    public int spaceValue = 0;       /** *//** Creates a new instance of MyCanvas */    public MyCanvas() {    //随机填充数组    for(int i=0;i<4;i++){    for(int j=0;j<3;j++){    pics[i][j] = i*3 + j + 1;    }    }    pics[0][3] = 0;       Random rand = new Random();    for(int i=0; i<4; i++){    int x1 = rand.nextInt(3);    int y1 = rand.nextInt(4);    int x2 = rand.nextInt(3);    int y2 = rand.nextInt(4);    int n = pics[y1][x1];    pics[y1][x1] = pics[y2][x2];    pics[y2][x2] = n;    }       //载入图片    for(int i=0; i<13; i++){    try{    images[i] = Image.createImage("/" + String.valueOf(i) + ".png");    }catch(Exception e){    //不做处理    }    }    }       public void clearBackground(Graphics g){    int color = g.getColor();    g.setColor(0xcccccc);    g.fillRect(0,0,getWidth(),getHeight());    g.setColor(color);    }       public void paint(Graphics g){    //清除背景    clearBackground(g);       //绘制网格    g.setColor(0x000000);    g.drawRect(1,3,236,284);    g.drawLine(1,74,237,74);    g.drawLine(1,145,178,145);    g.drawLine(1,216,178,216);    g.drawLine(60,3,60,287);    g.drawLine(119,3,119,287);    g.drawLine(178,3,178,287);       //根据pics数组和images数组的内容绘图到网格中    for(int i=0; i<4; i++){    for(int j=0; j<3; j++){    g.drawImage(images[pics[i][j]],j*59+2,i*71+4,Graphics.TOP|Graphics.LEFT);    }    }    g.drawImage(images[pics[0][3]],179,4,Graphics.TOP|Graphics.LEFT);       //绘制所用的步骤    g.drawString("步数:",182,140,Graphics.TOP|Graphics.LEFT);    g.setColor(0xffffff);    g.fillRect(182,158,50,18);    g.setColor(0xff0000);    g.drawString(String.valueOf(step),187,160,Graphics.TOP|Graphics.LEFT);       }          public void keyPressed(int keyCode){    switch(getGameAction(keyCode)){    case RIGHT:    right();    break;    case LEFT:    left();    break;    case UP:    up();    break;    case DOWN:    down();    break;    }    repaint();    }       public void up(){    if(spaceY < 3){    pics[spaceY][spaceX] = pics[spaceY+1][spaceX];    pics[spaceY+1][spaceX] = 0;    spaceY ++;    step ++;    }    }       public void down(){    if(spaceY >0){    pics[spaceY][spaceX] = pics[spaceY-1][spaceX];    pics[spaceY-1][spaceX] = 0;    spaceY --;    step ++;    }       }       public void left(){    int rightLimit = 2;    if(spaceY == 0){    rightLimit = 3;    }    if(spaceX < rightLimit){    pics[spaceY][spaceX] = pics[spaceY][spaceX+1];    pics[spaceY][spaceX+1] = 0;    spaceX ++;    step ++;    }       }       public void right(){    if(spaceX > 0 ){    pics[spaceY][spaceX] = pics[spaceY][spaceX -1];    pics[spaceY][spaceX-1] = 0;    spaceX --;    step ++;    }       }   }

  运行项目,得到如下的效果,使用上下左右四个键可以移动图片:

  游戏过程中的截图:

  游戏完成后的截图:

  当然,大家也可以自己添加拼图完成后的判断代码,在拼图成功后自动弹出提示信息。

0
相关文章