<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>O I P O P - 私人领域 &#187; JAVA开发</title>
	<atom:link href="http://blog.oipop.com/archives/category/java/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.oipop.com</link>
	<description>From the Internet, For the Internet.</description>
	<lastBuildDate>Mon, 21 Jun 2010 21:13:40 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>j2me中Command出现的优先顺序</title>
		<link>http://blog.oipop.com/archives/55</link>
		<comments>http://blog.oipop.com/archives/55#comments</comments>
		<pubDate>Sun, 16 Aug 2009 11:31:07 +0000</pubDate>
		<dc:creator>Kinsta</dc:creator>
				<category><![CDATA[J2ME开发]]></category>
		<category><![CDATA[JAVA开发]]></category>
		<category><![CDATA[J2ME]]></category>
		<category><![CDATA[手机编程]]></category>

		<guid isPermaLink="false">http://blog.oipop.com/?p=55</guid>
		<description><![CDATA[其实这是有一套规格可循的。规则如下：
1.先比较每个Command物件的命令型态，优先顺序越高的越先出现。
在Command物件之中共定义了八种命令型态，从优先顺序最高到最低列表如下：
Command.BACK Command.BACK
Command.CANCEL Command.CANCEL
Command.EXIT Command.EXIT
Command.HELP Command.HELP
Command.ITEM Command.ITEM
Command.OK Command.OK
Command.SCREEN Command.SCREEN
Command.STOP Command.STOP
2.如果命令型态相同，就比较其优先权，设定值越低的越先出现。
3.如果优先权相同，就以利用addCommand()加入画面的先后顺序决定。
]]></description>
			<content:encoded><![CDATA[<p>其实这是有一套规格可循的。规则如下：<br />
1.先比较每个Command物件的命令型态，优先顺序越高的越先出现。<br />
在Command物件之中共定义了八种命令型态，从优先顺序最高到最低列表如下：<br />
Command.BACK Command.BACK<br />
Command.CANCEL Command.CANCEL<br />
Command.EXIT Command.EXIT<br />
Command.HELP Command.HELP<br />
Command.ITEM Command.ITEM<br />
Command.OK Command.OK<br />
Command.SCREEN Command.SCREEN<br />
Command.STOP Command.STOP<br />
2.如果命令型态相同，就比较其优先权，设定值越低的越先出现。<br />
3.如果优先权相同，就以利用addCommand()加入画面的先后顺序决定。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oipop.com/archives/55/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>使用线程创建的三种方式实现j2me联网功能</title>
		<link>http://blog.oipop.com/archives/52</link>
		<comments>http://blog.oipop.com/archives/52#comments</comments>
		<pubDate>Fri, 14 Aug 2009 13:29:34 +0000</pubDate>
		<dc:creator>Kinsta</dc:creator>
				<category><![CDATA[J2ME开发]]></category>
		<category><![CDATA[J2ME]]></category>
		<category><![CDATA[JAVA开发]]></category>
		<category><![CDATA[手机编程]]></category>

		<guid isPermaLink="false">http://blog.oipop.com/?p=52</guid>
		<description><![CDATA[在j2me联网时，在eclipse控制台下有一个警告：“若要避免潜在的死锁，应该在commandAction()处理程序之外的其他线程中执行可能会阻塞的，操作（如网络连接）。
为了避免潜在的死锁，我们经常把把联网的代码部分写到一个线程中去执行。
而实际应用中，网络连接的事务也都是使用一个单独的线程进行的。

线程的创建可以使用Runnable接口来实现，也可以使用Thread类实现，还可以以匿名内部类的方式创建。在本文中，分别用这三种方式给出了j2me联网的例子。
代码均测试通过。可以直接使用。
1.通过继承Thread类创建
  import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class OpenConn implements Runnable {
 private HttpURLConnection conn;
 private URL url;
 // Thread thread1;
 public OpenConn(String url) throws MalformedURLException {
  this.url = new URL(url);
 }
 public void run() {
  try {
   conn = (HttpURLConnection) url.openConnection();
  } catch (IOException e) {
   e.printStackTrace();
   url = null;
  }
 }
 public HttpURLConnection getConn() {
  return conn;
 }
 public static void main(String[] args) throws Exception {
  // 创建Runnable类
  OpenConn openConn = [...]]]></description>
			<content:encoded><![CDATA[<p>在j2me联网时，在eclipse控制台下有一个警告：“若要避免潜在的死锁，应该在commandAction()处理程序之外的其他线程中执行可能会阻塞的，操作（如网络连接）。<br />
为了避免潜在的死锁，我们经常把把联网的代码部分写到一个线程中去执行。<br />
而实际应用中，网络连接的事务也都是使用一个单独的线程进行的。<br />
<span id="more-52"></span><br />
线程的创建可以使用Runnable接口来实现，也可以使用Thread类实现，还可以以匿名内部类的方式创建。在本文中，分别用这三种方式给出了j2me联网的例子。<br />
代码均测试通过。可以直接使用。<br />
1.通过继承Thread类创建</p>
<p>  import java.io.BufferedReader;<br />
import java.io.IOException;<br />
import java.io.InputStreamReader;<br />
import java.io.Reader;<br />
import java.net.HttpURLConnection;<br />
import java.net.MalformedURLException;<br />
import java.net.URL;</p>
<p>public class OpenConn implements Runnable {<br />
 private HttpURLConnection conn;<br />
 private URL url;</p>
<p> // Thread thread1;</p>
<p> public OpenConn(String url) throws MalformedURLException {<br />
  this.url = new URL(url);<br />
 }</p>
<p> public void run() {<br />
  try {<br />
   conn = (HttpURLConnection) url.openConnection();<br />
  } catch (IOException e) {<br />
   e.printStackTrace();<br />
   url = null;<br />
  }<br />
 }</p>
<p> public HttpURLConnection getConn() {<br />
  return conn;<br />
 }</p>
<p> public static void main(String[] args) throws Exception {<br />
  // 创建Runnable类<br />
  OpenConn openConn = new OpenConn(&#8220;<a href="http://www.google.com/">http://www.google.com</a>&#8220;);<br />
  // 创建线程<br />
  Thread thread = new Thread(openConn);<br />
  // openConn.thread1=thread;<br />
  thread.start();<br />
  thread.join(10000);// wait 10 seconds<br />
  HttpURLConnection c = openConn.getConn();<br />
  if (c != null) {<br />
   System.out.println(&#8220;连接网络成功&#8230;&#8221;);<br />
   BufferedReader r = new BufferedReader(new InputStreamReader(c<br />
     .getInputStream()));<br />
   String s = r.readLine();<br />
   while (s != null) {<br />
    System.out.println(s);<br />
    s = r.readLine();<br />
   }<br />
  } else {<br />
   System.out.println(&#8220;超时错误,连接网络失败&#8230;&#8221;);<br />
  }<br />
 }<br />
} <br />
2.通过引用Runnable接口创建</p>
<p>import java.io.BufferedReader;<br />
import java.io.IOException;<br />
import java.io.InputStreamReader;<br />
import java.io.Reader;<br />
import java.net.HttpURLConnection;<br />
import java.net.MalformedURLException;<br />
import java.net.URL;</p>
<p>public class OpenConn2 extends Thread {<br />
 private HttpURLConnection conn;<br />
 private URL url;</p>
<p> public OpenConn2(String url) throws MalformedURLException {<br />
  this.url = new URL(url);<br />
 }</p>
<p> public void run() {<br />
  try {<br />
   conn = (HttpURLConnection) url.openConnection();<br />
  } catch (IOException e) {<br />
   e.printStackTrace();<br />
   url = null;<br />
  }<br />
 }</p>
<p> public HttpURLConnection getConn() {<br />
  return conn;<br />
 }</p>
<p> public static void main(String[] args) throws Exception {<br />
  OpenConn2 openConn = new OpenConn2(&#8220;<a href="http://www.google.com/">http://www.google.com</a>&#8220;);<br />
  openConn.start();<br />
  openConn.join(10000);// wait 10 seconds<br />
  HttpURLConnection c = openConn.getConn();<br />
  if (c != null) {<br />
   System.out.println(&#8220;连接网络成功&#8230;&#8221;);<br />
   BufferedReader r = new BufferedReader(new InputStreamReader(c<br />
     .getInputStream()));<br />
   String s = r.readLine();<br />
   while (s != null) {<br />
    System.out.println(s);<br />
    s = r.readLine();<br />
   }<br />
  } else {<br />
   System.out.println(&#8220;超时错误,连接网络失败&#8230;&#8221;);<br />
  }<br />
 }<br />
}<br />
3.以匿名内部类的方式创建<br />
即在一个方法中创建线程，当方法被调用时，线程即启动，如下：<br />
import java.io.BufferedReader;<br />
import java.io.IOException;<br />
import java.io.InputStreamReader;<br />
import java.net.HttpURLConnection;<br />
import java.net.URL;</p>
<p>public class OpenConn3 {<br />
 private HttpURLConnection conn;<br />
 private URL url;<br />
 <br />
 public static void main(String[] args){<br />
  try{<br />
   OpenConn3 open3= new OpenConn3();<br />
   open3.strartMyThread();<br />
  }catch(Exception ex){<br />
   System.out.println(ex.toString());<br />
  }<br />
 }<br />
  public void strartMyThread() throws Exception{<br />
   this.url =new URL(&#8220;<a href="http://www.google.com/">http://www.google.com</a>&#8220;);<br />
         java.lang.Runnable runner=new Runnable(){<br />
          public void run(){<br />
           try {<br />
            conn = (HttpURLConnection) url.openConnection();<br />
           } catch (IOException e) {<br />
            e.printStackTrace();<br />
            url = null;<br />
           }<br />
          }</p>
<p>         };<br />
         Thread openConn=new Thread(runner);<br />
         openConn.start();<br />
         openConn.join(10000);// wait 10 seconds</p>
<p>   if (conn != null) {<br />
    System.out.println(&#8220;连接网络成功&#8230;&#8221;);<br />
    BufferedReader r = new BufferedReader(new InputStreamReader(conn<br />
      .getInputStream()));<br />
    String s = r.readLine();<br />
    while (s != null) {<br />
     System.out.println(s);<br />
     s = r.readLine();<br />
    }<br />
   } else {<br />
    System.out.println(&#8220;超时错误,连接网络失败&#8230;&#8221;);<br />
   }</p>
<p>  }<br />
}</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oipop.com/archives/52/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>J2ME手机屏幕切换</title>
		<link>http://blog.oipop.com/archives/48</link>
		<comments>http://blog.oipop.com/archives/48#comments</comments>
		<pubDate>Sat, 01 Aug 2009 01:51:36 +0000</pubDate>
		<dc:creator>Kinsta</dc:creator>
				<category><![CDATA[JAVA开发]]></category>
		<category><![CDATA[J2ME]]></category>
		<category><![CDATA[手机编程]]></category>

		<guid isPermaLink="false">http://blog.oipop.com/?p=48</guid>
		<description><![CDATA[在编写手机程序时，经常要进行各个屏幕间的切换
功能：在主程序中有多个按钮，每一个按钮对应一个功能，每一个功能要不同的屏幕(元素)表现出来。 实现： 一、主程序中必然定义了一个display对像，如private Display display,它表示当前的屏幕。还有一些Displayable对像。如form，textfield等都是displayable的子类。在主程序中通过dipslay.sercurrent(displayable实例名); 即可将当displayable实例加入当前的屏幕。以下程序：
private Display display=Display.getDisplay(this); 
private Form form = new Form(“New Form“); 
public void startapp() 
{ 
display.setcurrent(form); 
}
作用是将form添加到当前的屏幕当中。
二、要想进行屏幕间的切换，只要将你想显示的东东放到到主程序的display对象中即可。主程序中定义了一个display，则要在另一个屏幕(我姑且把它称之为目标屏幕)中引用到主程序的display。

用以下代码说明：
mainmidlet.java：主程序，一个标准的midlet。
import javax.microedition.midlet.midlet; 
import javax.microedition.lcdui.*;
public class mainmidlet extends midlet implements commandlistener {
private display display; 
private form form = new form(&#8220;wellcome!!&#8221;); 
private command okcommand = new command(&#8220;ok&#8221;,command.ok,1);
//选择ok,换到下一个屏幕 
private form ns ; 
private stringitem si = new stringitem(&#8220;first screen&#8221;,&#8221;~_~&#8221;); 
public mainmidlet() 
{ 
    form.addcommand(okcommand); 
    form.append(si); 
} 
public void startapp() { 
    display = display.getdisplay(this);
    [...]]]></description>
			<content:encoded><![CDATA[<p>在编写手机程序时，经常要进行各个屏幕间的切换<br />
功能：在主程序中有多个按钮，每一个按钮对应一个功能，每一个功能要不同的屏幕(元素)表现出来。 实现： 一、主程序中必然定义了一个display对像，如private Display display,它表示当前的屏幕。还有一些Displayable对像。如form，textfield等都是displayable的子类。在主程序中通过dipslay.sercurrent(displayable实例名); 即可将当displayable实例加入当前的屏幕。以下程序：<br />
private Display display=Display.getDisplay(this); <br />
private Form form = new Form(“New Form“); <br />
public void startapp() <br />
{ <br />
display.setcurrent(form); <br />
}<br />
作用是将form添加到当前的屏幕当中。<br />
二、要想进行屏幕间的切换，只要将你想显示的东东放到到主程序的display对象中即可。主程序中定义了一个display，则要在另一个屏幕(我姑且把它称之为目标屏幕)中引用到主程序的display。<br />
<span id="more-48"></span><br />
用以下代码说明：<br />
mainmidlet.java：主程序，一个标准的midlet。<br />
import javax.microedition.midlet.midlet; <br />
import javax.microedition.lcdui.*;</p>
<p>public class mainmidlet extends midlet implements commandlistener {</p>
<p>private display display; <br />
private form form = new form(&#8220;wellcome!!&#8221;); <br />
private command okcommand = new command(&#8220;ok&#8221;,command.ok,1);<br />
//选择ok,换到下一个屏幕 <br />
private form ns ; <br />
private stringitem si = new stringitem(&#8220;first screen&#8221;,&#8221;~_~&#8221;); <br />
public mainmidlet() <br />
{ <br />
    form.addcommand(okcommand); <br />
    form.append(si); <br />
} <br />
public void startapp() { <br />
    display = display.getdisplay(this);</p>
<p>    display.setcurrent(form); <br />
    form.setcommandlistener(this);//对form加入commandlistener</p>
<p>} <br />
public void pauseapp() {</p>
<p>} <br />
public void destroyapp(boolean b){</p>
<p>} <br />
public void commandaction(command c,displayable s) <br />
{ <br />
    if(c==okcommand) <br />
    { <br />
        ns = new nextscreen(display,form);//最关键的地方在这里：form：将父屏幕对象传下去，方便后退时返回父屏幕) <br />
        display.setcurrent(ns); <br />
    }</p>
<p>}</p>
<p>} <br />
在这个midlet中，定义了一个display对像display。 以及一个两个displayable对象form form及stringitem si。运行后显示在屏幕当中。 还有个一command okcommand，其作用是触发下一个屏幕。 在public void commandlistener中可以看到，当当前按下的按钮是okcommand时，初始化一个nextscreen对象 ns = new nextscreen(display,form); 将display和form传入，作用就是进行屏幕的切换。 下面是nextscreen的实现： nextscreen.java 第二个屏幕的代码<br />
import javax.microedition.lcdui.*; <br />
public class nextscreen extends form implements commandlistener {</p>
<p>private display display; <br />
private displayable parent; <br />
private command backcommand = new command(&#8220;back&#8221;,command.back,1); <br />
private stringitem si = new stringitem(&#8220;secondscrean&#8221;,&#8221;~_~&#8221;); <br />
public nextscreen(display d,displayable p) <br />
{ <br />
    super(&#8220;nextscreen&#8221;); <br />
    display = d; <br />
    parent = p; <br />
    append(si); <br />
    addcommand(backcommand); <br />
    setcommandlistener(this);</p>
<p>} <br />
public void commandaction(command c,displayable s) <br />
{ <br />
//返回上一个屏幕 <br />
    if(c==backcommand) <br />
    { <br />
    display.setcurrent(parent); <br />
    } <br />
}</p>
<p>} <br />
它继承自form类。 在nextscreen中又定义了一个display display，将用它来标识当前的元素显示在哪一个屏幕中。 一个form form，一个stringitem si。这是当前屏幕中要显示的东东：) 构造函数中的super(&#8220;secondscreen&#8221;);的作用是使得nextscreen可以直接调中其父类form中的函数。 backcommand的作用是返回上一个屏幕。 将form，si及backcommand加入nextscreen中，一个nextscreen的实例就完成了。在主程序(mainmidlet)中，就是ns。<br />
接下来，最关键的地方，就是在mainmidlet中的这一句：display.setcurrent(ns); 就是把ns在当前的屏幕中显示出来!这样就可以看到nextscreen中定义的各个元素(form,si)了!<br />
然后想返回原屏幕，怎么办呢？这时nextscreen中的backcommand就起作用了。 仔细看这两句： 在mainmidlet.java中： ns = new nextscreen(display,form); 它将form也传了进去。它有什么用呢？ 在nextscreen的构造函数中： dispaly =d; 这一句其实等于：nextscreen.display = mainmidlet.display; 这样，nextscreen就得到了当前的屏幕，它就随意的在上面放东东了。 parent = p; 这一句其实等于：nextscreen.parent = mainmidlet.form; 从字面意思不难理解，原来是把主程序的form当成parent(父母)，这样就得到当前屏幕的前一个屏幕中所显示的内容!! 然后在commandaction中，如果backcommand按下了，则执行display.sercurrent(parent);这样，又把原来的屏幕给show出来了：)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oipop.com/archives/48/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>深入理解Canvas类的使用(一)</title>
		<link>http://blog.oipop.com/archives/41</link>
		<comments>http://blog.oipop.com/archives/41#comments</comments>
		<pubDate>Mon, 27 Jul 2009 01:52:14 +0000</pubDate>
		<dc:creator>Kinsta</dc:creator>
				<category><![CDATA[JAVA开发]]></category>
		<category><![CDATA[J2ME]]></category>
		<category><![CDATA[手机编程]]></category>

		<guid isPermaLink="false">http://blog.oipop.com/?p=41</guid>
		<description><![CDATA[       在J2ME游戏编程中，Canvas类是最常用的类之一，该类提供了获得手机屏幕属性、绘制界面以及事件处理等很多实用的功能，下面就系统的介绍一下该类的使用，并结合实际说明一下在实际的使用过程中需要注意的一些问题。
       Canvas类是Displayable的子类，主要用来需要处理低级事件，例如键盘按键事件等，以及需要绘制屏幕的程序。在实际的使用过程，一般都通过继承Canvas来利用该类提供的功能。Canvas类是一个抽象类，继承该类的时候必须覆盖paint方法。

       Canvas类的功能主要包含以下几类：
1、  获得手机屏幕属性
l         getHeight——获得屏幕可用高度
l         getWidth——获得屏幕宽度
l         isDoubleBuffered——是否支持双缓冲
l         hasPointerEvents——是否支持指针设备
l         hasPointerMotionEvents——是否支持指针动作，例如拖拉事件
l         hasRepeatEvents——是否支持重复按键
实际开发过程中，可以在程序中直接调用这些方法，通过返回值获得相应的属性信息。
2、  绘制方法
l         paint——绘制方法
l         repaint——重新绘制方法
paint方法需要在界面类中覆盖，然后就可以书写功能，而再需要重新绘制的时候手动调用repaint方法。
3、  事件处理
低级用户界面的事件处理分为两种：按键事件和指针事件(处理触摸屏手机的低级事件)。
支持按键事件的方法主要有三个：
l         keyPressed——按键按下的事件
l         keyReleased——按键释放的事件
l         keyRepeated——重复按键的事件
支持指针事件的方法也有三个：
l         pointerPressed——指针设备按下事件
l         pointerReleased——指针设备释放事件
l         pointerDragged——指针设备拖拉事件
在实际的编程中，只需要在界面类中覆盖这些方法，然后在方法的内部书写代码即可，在发生这些事件的时候，系统会自动调用这些方法。
 
 
4、  其他方法
l         getGameAction——将按键映射成游戏动作
l         getKeyCode——将游戏动作转换为键值
l         getKeyName——将键值转换为按键名称
l         hideNotify——在Canvas界面被隐藏的时候系统自动调用该方法
l         showNotify——当Canvas界面显示的时候系统自动调用该方法
l         serviceRepaints——强制系统重新绘制
以上方法除了hideNotify、showNotify需要在子类中覆盖，系统会自动调用以外，其他的方法都可以直接调用。
5、  系统的熟悉主要分为两个部分：
l         按键的键值
KEY_NUM0、KEY_NUM1、KEY_NUM2、KEY_NUM3、KEY_NUM4、KEY_NUM5、KEY_NUM6、KEY_NUM7、KEY_NUM8、KEY_NUM9分别对应手机键盘的0-9数字键，KEY_STAR对应*号键，KEY_POUND对应#号键。各个功能键的键值在Canvas类没有进行定义，所以各个厂商，甚至厂商的不同型号手机之间，的键值都有所不同。但是功能键的键值均小于0。
 
 
l         游戏动作
UP、DOWN、LEFT、RIGHT和FIRE，分别对应上、下、左、右和确定键，在实际的手机中一般分别对应2、8、4、6和5键以及功能键中的方向键。GAME_A、GAME_B、GAME_C、GAME_D分别对应游戏中的A、B、C和D键，分别映射成手机上的1、3、7、9键，或者是7、9、*和#键。
在实际的事件处理中，使用游戏可以达到在不同的手机之间通用。
 
 
              在MIDP2.0中，又新增了两个方法，分别是：
l         setFullScreenMode——控制屏幕是全屏幕显示还是一般模式显示
l         sizeChanged——当屏幕尺寸变化的时候，系统会自动调用该方法。
上面系统的介绍了Canvas类提供的功能，下面就介绍一下它的使用。当调用Display对象的setCurrent方法显示Canvas界面时，系统首先调用Canvas对象的构造方法，然后调用paint方法实现绘制，这样我们就可以看到实际的界面了。而以后，当界面坐标发生变化以后，必须手动调用repaint方法实现绘制。
以下是一些在实际的编程过程中，需要注意的一些问题：
l         坐标参数化或者根据屏幕的宽度和高度生成坐标，从而提高界面的移植性。
l         在程序运行过程中，paint方法经常被反复调用，所以一般在该方法中只放置绘制的代码，而把逻辑处理的代码放在别的位置。
l         在进行低级事件处理代码编写中，对于游戏按键，尽量使用游戏动作进行编程，其他按键才直接使用键值，从而提高事件处理代码的移植性。
l         因为hideNotify和showNotify方法会在界面隐藏和重新显示时，被系统自动调用，所以可以覆盖这两个方法，在其中实现暂停的逻辑。
l         尽量使用双缓冲技术，避免屏幕的闪烁，除非手机不支持双缓冲。
l         显示其他界面的时候，注意要关闭线程，并释放资源。
]]></description>
			<content:encoded><![CDATA[<p>       在J2ME游戏编程中，Canvas类是最常用的类之一，该类提供了获得手机屏幕属性、绘制界面以及事件处理等很多实用的功能，下面就系统的介绍一下该类的使用，并结合实际说明一下在实际的使用过程中需要注意的一些问题。</p>
<p>       Canvas类是Displayable的子类，主要用来需要处理低级事件，例如键盘按键事件等，以及需要绘制屏幕的程序。在实际的使用过程，一般都通过继承Canvas来利用该类提供的功能。Canvas类是一个抽象类，继承该类的时候必须覆盖paint方法。</p>
<p><span id="more-41"></span></p>
<p>       Canvas类的功能主要包含以下几类：</p>
<p>1、  获得手机屏幕属性</p>
<p>l         getHeight——获得屏幕可用高度</p>
<p>l         getWidth——获得屏幕宽度</p>
<p>l         isDoubleBuffered——是否支持双缓冲</p>
<p>l         hasPointerEvents——是否支持指针设备</p>
<p>l         hasPointerMotionEvents——是否支持指针动作，例如拖拉事件</p>
<p>l         hasRepeatEvents——是否支持重复按键</p>
<p>实际开发过程中，可以在程序中直接调用这些方法，通过返回值获得相应的属性信息。</p>
<p>2、  绘制方法</p>
<p>l         paint——绘制方法</p>
<p>l         repaint——重新绘制方法</p>
<p>paint方法需要在界面类中覆盖，然后就可以书写功能，而再需要重新绘制的时候手动调用repaint方法。</p>
<p>3、  事件处理</p>
<p>低级用户界面的事件处理分为两种：按键事件和指针事件(处理触摸屏手机的低级事件)。</p>
<p>支持按键事件的方法主要有三个：</p>
<p>l         keyPressed——按键按下的事件</p>
<p>l         keyReleased——按键释放的事件</p>
<p>l         keyRepeated——重复按键的事件</p>
<p>支持指针事件的方法也有三个：</p>
<p>l         pointerPressed——指针设备按下事件</p>
<p>l         pointerReleased——指针设备释放事件</p>
<p>l         pointerDragged——指针设备拖拉事件</p>
<p>在实际的编程中，只需要在界面类中覆盖这些方法，然后在方法的内部书写代码即可，在发生这些事件的时候，系统会自动调用这些方法。</p>
<p> </p>
<p> </p>
<p>4、  其他方法</p>
<p>l         getGameAction——将按键映射成游戏动作</p>
<p>l         getKeyCode——将游戏动作转换为键值</p>
<p>l         getKeyName——将键值转换为按键名称</p>
<p>l         hideNotify——在Canvas界面被隐藏的时候系统自动调用该方法</p>
<p>l         showNotify——当Canvas界面显示的时候系统自动调用该方法</p>
<p>l         serviceRepaints——强制系统重新绘制</p>
<p>以上方法除了hideNotify、showNotify需要在子类中覆盖，系统会自动调用以外，其他的方法都可以直接调用。</p>
<p>5、  系统的熟悉主要分为两个部分：</p>
<p>l         按键的键值</p>
<p>KEY_NUM0、KEY_NUM1、KEY_NUM2、KEY_NUM3、KEY_NUM4、KEY_NUM5、KEY_NUM6、KEY_NUM7、KEY_NUM8、KEY_NUM9分别对应手机键盘的0-9数字键，KEY_STAR对应*号键，KEY_POUND对应#号键。各个功能键的键值在Canvas类没有进行定义，所以各个厂商，甚至厂商的不同型号手机之间，的键值都有所不同。但是功能键的键值均小于0。</p>
<p> </p>
<p> </p>
<p>l         游戏动作</p>
<p>UP、DOWN、LEFT、RIGHT和FIRE，分别对应上、下、左、右和确定键，在实际的手机中一般分别对应2、8、4、6和5键以及功能键中的方向键。GAME_A、GAME_B、GAME_C、GAME_D分别对应游戏中的A、B、C和D键，分别映射成手机上的1、3、7、9键，或者是7、9、*和#键。</p>
<p>在实际的事件处理中，使用游戏可以达到在不同的手机之间通用。</p>
<p> </p>
<p> </p>
<p>              在MIDP2.0中，又新增了两个方法，分别是：</p>
<p>l         setFullScreenMode——控制屏幕是全屏幕显示还是一般模式显示</p>
<p>l         sizeChanged——当屏幕尺寸变化的时候，系统会自动调用该方法。</p>
<p>上面系统的介绍了Canvas类提供的功能，下面就介绍一下它的使用。当调用Display对象的setCurrent方法显示Canvas界面时，系统首先调用Canvas对象的构造方法，然后调用paint方法实现绘制，这样我们就可以看到实际的界面了。而以后，当界面坐标发生变化以后，必须手动调用repaint方法实现绘制。</p>
<p>以下是一些在实际的编程过程中，需要注意的一些问题：</p>
<p>l         坐标参数化或者根据屏幕的宽度和高度生成坐标，从而提高界面的移植性。</p>
<p>l         在程序运行过程中，paint方法经常被反复调用，所以一般在该方法中只放置绘制的代码，而把逻辑处理的代码放在别的位置。</p>
<p>l         在进行低级事件处理代码编写中，对于游戏按键，尽量使用游戏动作进行编程，其他按键才直接使用键值，从而提高事件处理代码的移植性。</p>
<p>l         因为hideNotify和showNotify方法会在界面隐藏和重新显示时，被系统自动调用，所以可以覆盖这两个方法，在其中实现暂停的逻辑。</p>
<p>l         尽量使用双缓冲技术，避免屏幕的闪烁，除非手机不支持双缓冲。</p>
<p>l         显示其他界面的时候，注意要关闭线程，并释放资源。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.oipop.com/archives/41/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
