在J2ME中,Profiles是用于定義用戶(hù)接口A(yíng)PI的。MIDP定義了兩種這類(lèi)API,被稱(chēng)為高層API和底層API,高層API要求你使用面向事務(wù)的抽象來(lái)定義用戶(hù)接口做什么。你并沒(méi)有對屏幕上所畫(huà)的東西的真正控制—實(shí)現選擇了對設備最佳的實(shí)現方式。高層API對于所有MIDP-enabled設備是可移植的,并且它是真正適合于商業(yè)應用的。更多有關(guān)高層API的信息請關(guān)注后續的J2ME技術(shù)Tips。
底層API是為游戲開(kāi)發(fā)人員準備的。不像高層API,底層API賦予你完全的對屏幕和事件的訪(fǎng)問(wèn)能力,這種訪(fǎng)問(wèn)能力是有代價(jià)的,因為這樣你將負責畫(huà)屏幕上所顯示的任何東西。你可以在同一個(gè)應用中同時(shí)使用高層API和底層API。把應用看作一副撲克牌,同時(shí)只能有一張是可見(jiàn)的(很象J2SE平臺上提供的Java.awt.CardLayout類(lèi)所提供的功能),每張卡片,可以被認為是MIDP詞匯中的屏幕(Screen),對于每一張或者使用高層API,或者使用底層API,但是不能同時(shí)使用。唯一的例外是使用命令對象,將在Tips的后面探討。
在MIDlet中使用底層API,編寫(xiě)一個(gè)Canvas類(lèi)的擴展類(lèi):
// Simple canvas
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class MyCanvas extends Canvas {private MIDlet midlet;
public MyCanvas( MIDlet midlet ){this.midlet = midlet;
}
protected void paint( Graphics g ){g.setColor( 255, 255, 255 );
g.fillRect( 0, 0, getWidth(), getHeight() );
g.setColor( 0, 0, 0 );
g.drawString( "Hello there!", getWidth()/2, 0,
g.TOP g.HCENTER );
}
}
所有的用戶(hù)接口類(lèi)都在javax.microedition.lcdui包中。注意你也需要到如javax.microedition.midlet包,因為你將為每一個(gè)canvas傳遞一個(gè)引用到MIDlet。你的canvas子類(lèi)必須實(shí)現一個(gè)繪圖方法,它是被系統調用來(lái)重畫(huà)屏幕的。繪圖方法是通過(guò)Graphics對象傳遞的,Graphics對象是用來(lái)定義標準的畫(huà)圖方法的,而這些都是你所需要的,例如,drawArc,drawLine,drawRect和drawString等。MyCanvas范例簡(jiǎn)單的將屏幕畫(huà)成白色來(lái)清楚屏幕,然后在屏幕的中間上方畫(huà)一條線(xiàn)(黑色的)。
你激活一個(gè)canvas是通過(guò)調用MIDlet的Display對象的setCurrent方法來(lái)實(shí)現的。通常在應用的MIDlet類(lèi)的startApp方法中調用:
// Simple MIDlet
import javax.microedition.midlet.*;
public class MyMIDlet extends MIDlet {private Display display;
private MyCanvas canvas;
public MyMIDlet(){display = Display.getDisplay( this );
canvas = new MyCanvas( this );
}
protected void startApp(){display.setCurrent( canvas );
}
protected void pauseApp(){}
protected void destroyApp( boolean unconditional ){}
public void exit(){destroyApp( true );
notifyDestroyed();
}
}
盡管這個(gè)MIDlet能工作,它有一個(gè)問(wèn)題:沒(méi)有明顯的方式可以從它退出。你需要引導用戶(hù)以某種方式輸入。有兩種方式可以實(shí)現:使用行輸入事件或使用命令事件。
n Canvas允許使用行輸入事件,是通過(guò)覆蓋canvas類(lèi)定義的適當的事件發(fā)送方法來(lái)實(shí)現的。事件生成的可用方法有:
n 按鍵(keyPressed,keyRepeated,和keyReleased)
n 使用指針(pointerPressed,pointerDragged和pointerReleased)如果指針在設備上可以使用的話(huà)
n 顯示canvas(showNotify,hideNotify)
例如,你可以增加一種方式結束應用,通過(guò)在canvas中定義一個(gè)keyPressed事件:
protected void keyPressed( int keyCode ){((MyMIDlet) midlet).exit();}在所有的鍵盤(pán)事件中,keycode識別按鍵并激發(fā)事件。正值表示Unicode字符,而負值是一個(gè)鍵無(wú)法被直觀(guān)的轉換成Unicode。為了避免
區分哪一個(gè)鍵表示哪一個(gè),這種有不同設備確定的問(wèn)題,canvas類(lèi)為常用鍵定義了一些限制。特別是,它定義了抽象游戲行為(UP, DOWN,
LEFT, RIGHT, FIRE, GAME_A, GAME_B, GAME_C, 和GAME_D)它們的鍵盤(pán)代碼映射圖可以實(shí)時(shí)定義。在它初始化過(guò)程中,設備可以調
用canvas.getGameAction來(lái)確定哪種鍵盤(pán)映射更適合于操作。你可以定義一個(gè)基礎類(lèi),就象:
public abstract class GameCanvas extends Canvas {protected MIDlet midlet;protected int fireKey;protected int leftKey;protected int rightKey;protected int upKey;protected int downKey;public GameCanvas( MIDlet midlet ){this.midlet = midlet;fireKey = getKeyCode( FIRE );leftKey = getKeyCode( LEFT );rightKey = getKeyCode( RIGHT );upKey = getKeyCode( UP );downKey = getKeyCode( DOWN );}}然后,擴展它,就象:
public class MyCanvas extends GameCanvas {private String message = "Press any key";public MyCanvas( MIDlet midlet ){super( midlet );}protected void paint( Graphics g ){g.setColor( 255, 255, 255 );g.fillRect( 0, 0, getWidth(), getHeight() );g.setColor( 0, 0, 0 );g.drawString( message, getWidth()/2, 0,g.TOP g.HCENTER );}protected void keyPressed( int keyCode ){if( keyCode == fireKey ){message = "FIRE";} else if( keyCode == leftKey ){message = "LEFT";} else if( keyCode == rightKey ){message = "RIGHT";} else if( keyCode == upKey ){message = "UP";} else if( keyCode == downKey ){message = "DOWN";} else {message = getKeyName( keyCode );}repaint();}}指針事件是可選項,因為不是所有的MIDP可用的設備都支持指針。你可以在指針有效的時(shí)候來(lái)使用它的優(yōu)勢。但是你不能夠假設它是可用的。你可以檢測
是否指針事件可以被激發(fā),通過(guò)調用Canvas.hasPointerEvents。指針事件方法獲取指針的位置:protected void pointerPressed( int x, int y ){// do something here}另一種方法引導用戶(hù)輸入是為canvas附加命令。一個(gè)命令是一個(gè)動(dòng)作的抽象表現。它有一個(gè)用戶(hù)定義的label, type和優(yōu)先級。設備使用type映射命令到相應的鍵或按鈕。例如,如果設備有一個(gè)標準的OK鍵,指定一個(gè)命令類(lèi)型為OK,確保OK按鈕激發(fā)這個(gè)命令。有效的類(lèi)型有BACK, CANCEL, EXIT, HELP,ITEM, OK, SCREEN, 和STOP。一部分或全部這些都可以映射到相同的按鍵或按鈕。這樣,當有沖突的時(shí)候,設備可以使用優(yōu)先級來(lái)適當的排列命令次序。優(yōu)先級是一個(gè)正整數,1是最高優(yōu)先級。命令是使用Command類(lèi)來(lái)創(chuàng )建的,如下:Command exitCommand = new Command( "Exit", Command.SCREEN, 1 );你使用addCommand方法來(lái)將命令添加到canvas:canvas.addCommand(exitCommand);你必須注冊命令,使用:setListener: canvas.setListener( listener ) ;監聽(tīng)器必須實(shí)現CommandListener借口。它對于主要的MIDlet類(lèi)來(lái)實(shí)現CommandListener來(lái)獲取exit命令是通用的,如下所示:// Simple MIDletimport javax.microedition.midlet.*;public class MyMIDlet extends MIDlet implementsCommandListener {private Display display;private MyCanvas canvas;private Command exitCommand = new Command("Exit", Command.SCREEN, 1 );public MyMIDlet(){display = Display.getDisplay( this );canvas = new MyCanvas( this );canvas.addCommand( exitCommand );canvas.setListener( this );}protected void startApp(){display.setCurrent( canvas );}protected void pauseApp(){}protected void destroyApp( boolean unconditional ){}public void exit(){destroyApp( true );notifyDestroyed();}public void commandAction( Command c, Displayable d ){if( c == exitCommand ){exit();}}}CommandListener接口定義一個(gè)簡(jiǎn)單的方法,commandAction,它在一個(gè)命令被激發(fā)的時(shí)候被調用。一個(gè)激發(fā)命令對象的引用被傳入,同時(shí)一個(gè)顯示對象的引用被引用,它是在它被激活的時(shí)候開(kāi)始動(dòng)作的。(同樣的命令可以在不同的canvas中共享并且高層API也是一樣可以被共享的)當然,監聽(tīng)器負責實(shí)際執行這個(gè)動(dòng)作。
聯(lián)系客服