j2medev“用户界面和多媒体”版面问题整理[0407更新]
| 出品商 | 產品名稱 | 產品版本 |
| J2medev.com | 版面有價值的問題合集 | 0.1 |
j2medev.com之“用戶界面和多媒體”版面
有價值問題的整理
歷史
| Version | Date | Creator | Description |
| 1.0.0.1 | 2006-4-4 | 鄭昀 | 草稿 |
| 1.0.0.2 | 2006-4-6 | 鄭昀 | 第二稿 |
?
1?全屏問題
?
全屏/FullCanvas/setFullScreenMode
| 關鍵詞 | 詳細描述 | ? | |
| SonyEricsson T630 | 該款手機的參數:索尼愛立信?T630 SonyEricssonT630R401 ProfileMIDP-1.0 ConfigurationCLDC-1.0。 “據我所知,不可以實現全屏顯示。” --- lulei204 | ? | |
| SonyEricsson K700c | k700c??直接用nokia的FullCanvas,可以全屏176 x 220。 k700c用midp2.0的那個this.setFullScreenMode(true);也是可以全屏的,176x220。 k700c直接用nokia的FullCanvas全屏好像是176*208,直接拿nokia60上的程序可以直接放進去。鍵值和60的也是相同的,只是多了一個返回鍵,我忘了值是多少了。用2.0的GameCanvas大小是176*220。 --- lulei204 | ? | |
| 不使用FullCanvas實現全屏的方法 | 為了用標準的SUN WTK2.1開發能兼容各種機型的MIDP2.0游戲,會遇到一個奇怪的全屏問題,在K700上好好的,到了Nokia上居然死活顯示一半,費了一番功夫后,終于不用FullCanvas實現了兼容K700和Nokia的全屏顯示,方法如下: 在索愛的K700上,實現全屏很簡單,如下寫法就可以了: public Canvas1() {?????????super(false); ????????this.setFullScreenMode(true); ????????this.width=getWidth(); ????????this.height=getHeight(); }?得到的屏幕大小是176*220。 Nokia上就比較奇怪了,這種方式取得的width和height居然是176*144。 需要加以下代碼修正一下: if(width>=176) {?????if(height<208) ????{ ?????????height=208; ????} }?繪圖部分都以width和height為基準。 另外canvas1不能繼承系統的GameCanvas,因為系統GameCanvas里的緩沖圖還是176*144的,畫出來就只能是半屏,我用j2me polish里的GameCanvas修改一下后,放到src里代替系統GameCanvas就OK了。 修正過的GameCanvas代碼如下: http://www.j2medev.com/bbs/dispbbs.asp? BoardID=19&ID=3218&replyID=&skin=1 ---alexhy | ||
| FullCanvas和setFullScreenMode()的區別 | setFullScreenMode用于MIDP2.0設備上。com.nokia.mid.ui.FullCanvas是Nokia UI API 1.1的包,用于MIDP2.0設備上,SonyEricsson手機也支持。 ? “FullCanvas是肯定可以實現全屏幕顯示的,但是MIDP2.0里面的setFullScreenMode()只是實現為盡量使用最大的屏幕空間,但是不一定是全屏幕,要看各個手機的實現。” ---mingjava “FullCanvas不能加Command;setFullScreenMode(true)可以加上Command()。只是我加上一個按鍵時,卻不管把它設在哪里,只能是右鍵響應。” ---風過留痕 | ||
| FullCanvas和Canvas,GameCanvas分別有什么不同 | “FullCanvas是Canvas的子類,實現全屏的功能,而且把按鍵針對nokia的手機進行了映射。其他沒有什么區別。” ---migjava “GameCanvas也是Canvas的子類,自MIDP2.0起提供,專門針對游戲增加了一些功能。在按鍵和顯示各方面的運用都和Canvas有較大的不同。” ---efei | ||
| Motorola的MIDP1.0手機 | “motorola如果不支持MIDP2.0,應該就沒辦法實現全屏了。全屏下的菜單很好實現,不用搞得象Command那么復雜,那個Command用起來就是很不爽,還是自己寫最好。” ---海標 | ||
| Nokia S60全屏后的Canvas高度 | “canvas. setFullScreenMode(true)后,一定讓他被繪制一次,系統會調用sizechange(int w,int h),w、h肯定是全屏的。僅調用setFullScreenMode (true)則好象各系統有不同處理。” ---atchome ? “You can call getWidth() getHeight() after Canvas.showNotify(). Then it will return the correct value. eg. 176*208” --- okboy001 ? “系統第一次回調paint()方法時可以獲得正確的屏幕尺寸 原因如atchome所說” --- imshark_jinni ? “在Nokia S60真機上這是一個BUG似乎: setFullScreenMode(true);調用之后, getHeight()返回的并不是全屏后的高度,比如他本應該返回208, 但是他卻返回144,所以,在真機測試時也要小心nokia s60的這個bug, 不要因為屏幕高度獲取不正確,導致fillRect與你預想不一致。 ? 以上這個BUG,起碼我的Nokia 7610就是這樣。 所以我必須在setFullScreenMode(true);全屏之后 通過下面代碼來獲取真實的canvas高度: ? Code: public abstract class PopupCanvas extends Canvas { 。。。。 /* ??????????*?針對Nokia全屏情況下getHeight的BUG,此函數出自于 ??????????* http://discussion.forum.nokia.com/f...?threadid=48826 ??????????*/ ?????????public int getHeight(){ ????????????????try{ ???????????????????????if("Nokia".compareTo( System.getProperty("microedition.platform").substring(0,5)) ?== 0) ??????????????????????????????return 208; ???????????????????????else ??????????????????????????????return super.getHeight(); ????????????????} ????????????????catch(Exception e){ ???????????????????????return super.getHeight(); ????????????????} ??????????????} }” ---zhengyun | ? | |
?
2 Image和ByteArray轉換問題
?
Image/byte[]/Convert
| 關鍵詞 | 詳細描述 | |
| Image對象轉換為byte[] | “image-(getGraphics)->graphic-(setClip,?對每個象素getColor)->原始byte[]” --- rypan ? “要是在?J2ME?的話,?看來只有?Image.getRGB()?能幫上: 還有做int[] -> byte[]?的動作,?可以考慮用?ByteArrayOutputStream + DataOutputStream,?把?int[]?用?dos.writeInt?的方法寫在?Byte array上. 當然可以用最老土的方法,?不知道那種快: byteArray[i] = intArray[j] & 0xFF; byteArray[i+1] = (intArray[j] >> 8)& 0xFF; byteArray[i+2] = (intArray[j] >> 16)& 0xFF; byteArray[i+3] = (intArray[j] >> 24)& 0xFF;” --- wapeter ? “ public static byte[] getByteArray(Image image) { ???????int raw[] = new int[image.getWidth() * image.getHeight()]; ???????image.getRGB(raw, 0, image.getWidth(), 0, 0, ??????????????image.getWidth(), image.getHeight()); ???????byte rawByte[] = new byte[image.getWidth() * image.getHeight() * 4]; ???????int n = 0; ???????for(int i = 0; i < raw.length; i++) ???????{ ??????????????int ARGB = raw[i]; ??????????????int a = (ARGB & 0xff000000) >> 24; ??????????????int r = (ARGB & 0xff0000) >> 16; ??????????????int g = (ARGB & 0xff00) >> 8; ??????????????int b = ARGB & 0xff; ??????????????rawByte[n] = (byte)b; ??????????????rawByte[n + 1] = (byte)g; ??????????????rawByte[n + 2] = (byte)r; ??????????????rawByte[n + 3] = (byte)a; ??????????????n += 4; ???????} ?????? ???????raw = null; ???????return rawByte; } ? 上面代碼進一步的解釋: ? 第一步: 如何獲得image對象的int數組呢?這個就簡單了可以通過獲得RGB數組就可以。Image對象中有直接的getRGB方法,不過這里的參數的位置和J2SE中不太一樣: javax.microedition.lcdui.Image.getRGB(int[] rgbData, int offset, int scanlength, int x, int y, int width, int height) 第一個是目標數組,第二個是偏移量,第三個是掃描的長度,后兩個是起始的位置,最后兩個是要取得的寬度和高度。其中掃描的長度一般大于等于獲取的寬度。 ? 第二步,把得到的Int數組再生成byte數組。 “???byteArray[i+0] = (rgbArray[i/4] >> 24); ???byteArray[i+1] = (rgbArray[i/4] >> 16) & 0x000000FF; ???byteArray[i+2] = (rgbArray[i/4] >>??8) & 0x000000FF; ???byteArray[i+3] = rgbArray[i/4] & 0x000000FF; ” 第一句,alpha channel; 第二句,red channel; 第三句,green channel; 第四句,blue channel。 ? 為什么有這些東西呢? 我們從一篇文章《介紹MIDP2.0新特性Alpha混合》摘要幾句: [quote] 在MIDP2.0中新增了Alpha混合特性...MIDP2.0 java doc中關于Alpha Processing的說明:在可修改圖片中的每個像素都必須是完全模糊的,在不可修改圖片中的每個像素可以是完全透明的,完全模糊的或者介于兩者之間的,也就是半透明... [/quote] ? 所以有了上面的Alpha channel。 ? [quote] 數組中的數值形式為0xAARRGGBB,其中AA代表透明度,后面的代表顏色值。 [/quote] 也就是說,AA就是Alpha,RR就是Red,GG就是Green,BB就是Blue。 ? 還有一句話概括的: [quote]444,表示圖形格式,好像Nokia S40的機器都是采用444格式表示RGB顏色的。就是紅,綠,藍各用4位表示,至于可以表示透明色ARGB的4444格式,應該是機器硬件實現的。[/quote]” ---zhengyun ? | |
| ? | ? | |
?
3 getRGB問題
?
getRGB/
| 關鍵詞 | 詳細描述 | |
| getRGB的參數意義 | “javax.microedition.lcdui.Image.getRGB(int[] rgbData, int offset, int scanlength, int x, int y, int width, int height) 第一個是目標數組,第二個是偏移量,第三個是掃描的長度,后兩個是起始的位置,最后兩個是要取得的寬度和高度。其中掃描的長度一般大于等于獲取的寬度。” --?whycloud ? “offset?是指要取的RGB值儲存在rgbData數組的起始位置,一般為0。如果offset不為0,使用rgbData數組就不方便了,因為要從offset開始的位置使用。而scanlength不對(如:|scanlength|<width)的話,就可能造成所取的rgbData值會有重復。 ? 在API文檔里面有一個公式,可以讓我們理解地更深刻: rgbData[offset + (a - x) + (b - y) * scanlength] = P(a, b) ? 其中P(a, b)表示在IMAGE數組中位置為(a,b)的像素點。 具體的內容可以參考API文檔。 其實MIDP2.0的getRGB()跟NOKIA的getPixels()是類似的。 ” --- xpanda | |
| ? | ? | |
?
4?字符串換行問題
?
drawString/Line Wrap/StringLayout
| 關鍵詞 | 詳細描述 | |
| 用g.drawString(); 要顯示的文字很多,那應該如何實現在Canvas上換行呢 | “StringLayout類可以自動排版,還能上下翻行。 代碼在 http://www.j2medev.com/bbs/dispbbs.asp?BoardID=11 &replyID=20309&id=3997&skin=0可以找到。 ” --- sakaipb “自動處理字符串折行顯示的封裝類Line Wrap 代碼以及如何使用的例子都可以從 http://fotomica.astrientlabs.com/downloads/textwrap.jsp?找到。?????? ” --- zhengyun | |
| ? | ? | |
?
5?字體問題
?
Font/setFont/摩托羅拉
| 關鍵詞 | 詳細描述 | |
| moto系列的手機是不是不支持用setFont來修改字體的大小呢? | “motoV360這機器就這德性。 ” --- Lcheer ? “好像moto的某些手機里只有一種字體,高度是17x17,而且下面還會被割去幾個象素。” --?lulei204 ? “MOTO中低端機型都只有一種字體,而且是中號字體。” --?summoner ? | |
| SonyEricsson?S700c 上用g.drawString()方法繪制的漢字為何很大? | “索愛S700c上面,Canvas?的drawString()方法繪制的漢字為何很大??一行最多顯示10個字左右。 用了Font的SIZE_SMALL還是一樣。” --webgl2005 “有的手機只支持一種字體,用Font的參數都沒有效果。” ---magicDragon | |
| 怎樣為nokia qd設置字體顏色? | “不知道為什么在QD上字體就只有黑色.怎么設置也不行. Image offImage????= Image.createImage(SCREEN_WIDTH, SCREEN_HEIGHT) ; Graphics offGraphics = offImage.getGraphics() ; offGraphics.setColor(0xffff00) ; offGraphics.drawString(……) ; 這么寫的話,字體永遠都是黑色的,但在paint()里直接用g.setColor()卻是正常的。” ---?海標 “setColor在非paint中得到的graphics中都無效。這是S60的bug。 ” ---蠟筆小刀 ? | |
| moto字體移植問題 | “有人說moto字體不好看,大小調整上給移植帶來很大麻煩,我以前也這么認為。 現在我覺得moto的字體還行。在沒有辦法的情況下,我們只好在程序上下功夫,讓字排列的更美觀、更好看。” --lulei204 “moto就是這樣,移植的時候狠不得把所有文字都去掉” --topig | |
?
?
6?重新播放音樂問題
?
player/stop/start
| 關鍵詞 | 詳細描述 | |
| 音樂停止播放后如何從起始位置重新播放? | “如果你的音樂自己播放完畢了,而用戶手動提交命令要求重新播放,那么你可以直接調用player.play()即可。或者一開始播放音樂的時候就利用player.setLoopCount設定循環播放次數。 ? 如果你希望音樂自動重新播放,那么就必須實現“播放器狀態更新事件”: 以下內容為程序代碼: //?綁定狀態更新事件過程 player.addPlayerListener(this); ? /* ?*?本類實現了PlayerListener接口。通過這個事件來告知媒體已經播放完畢 ?*/ public void playerUpdate(Player player, String event, Object data){ ???????System.out.println("Enter playerUpdate>>" + ?????????????????????event); ?????? ???????if(event == PlayerListener.END_OF_MEDIA){ ??????????????try{ ?????????????????????....??????????????????????? ??????????????}catch(Exception e){ ?????????????????????e.printStackTrace(); ??????????????} ???????} ???????else if(event == PlayerListener.STOPPED) ???????{ ?????????????System.out.println("playerUpdate>>PlayerListener.STOPPED"); ???????} ???????else if(event == PlayerListener.STARTED) ???????{ ?????????????System.out.println("playerUpdate>>PlayerListener.STARTED"); ???????} } ” --- zhengyun ? | |
| SonyEricsson K750手機上無法實現暫停,續播功能? | “發覺在索愛K750手機上無法實現暫停,續播功能。該功能在MOTO,NOKIA手機上可以使用。” --trysunset ? | |
?
7?MediaException問題
?
player/stop/start
| 關鍵詞 | 詳細描述 | |
| 播放MIDI時,真機上會爆出MediaException 異常,而在其他機器上可正常播放MIDI? | “is = getClass().getResourceAsStream("/title.mid"); ? if (is != null) { ?player_ = Manager.createPlayer(is, "audio/midi"); ????player_.setLoopCount(-1); ????player_.start(); } 這個代碼是我用來監測一款機器用的,在播放MIDI時,其真機上會爆出MediaException異常,而在其他機器上可正常播放MIDI! 有意思的是這個代碼用來播放WAV則是正常的,由于該PDA機自帶播放器,我將MIDI直接傳入其中播放時可以播放的,所以應該不會有MIDI格式不兼容的問題! ” --- imtrash ? “虛擬機不支持MIDI的播放!??我用過的NOKIA6630的手機就是這樣的!” --- zgly ? “你可以將虛擬機可以播放的音樂類型用下面的代碼 ???public void showForm() { ????????String[]??protocols, contentTypes; ? ????????protocols = Manager.getSupportedProtocols(null); ????????for (int i = 0; i < protocols.length; i++) { ????????????contentTypes = Manager.getSupportedContentTypes( protocols[i]); ????????????for (int j = 0; j < contentTypes.length; j++) { ????????????????m_errForm.append(protocols[i] + ":" + contentTypes[j]);? ????????????} ????????} ????} 將信息顯示在一個FORM里!” --- zgly ? “必須明確的一點是,我們的MIDlet是運行在Java ME平臺環境下的。??不一定設備提供的功能在Java ME平臺都得到了實現!” --- mingjava ? | |
| 在真機測試中, Nokia7610彈出一個錯誤: “javax. microedition. media. MediaException: -18”? | “很明顯是nokia 7610上不支持這種媒體格式設置media time,所以拋出了MediaException。 把p.setMediaTime(5 * SECS_TO_MICROSECS);刪除即可” --?mingjava ? | |
| “error opening MIDI/tone device”或“fail in writing data to native”? | “播放MIDI的代碼在k700和6600上都沒問題,在moto上不知道怎么回事卻報如下異常: javax.microedition.media.MediaException: fail in writing data to native 用e680i的模擬器仍然會報錯, 不過報出來的是: javax.microedition.media.MediaException: error opening MIDI/tone device ????????at com.sun.mmedia.MIDIPlayer.doPrefetch(+19) ????????at com.sun.mmedia.BasicPlayer.prefetch(+34) 最后找到原因了,moto的機器不能同時有兩個midi的player在prefetch()中,即使前面那個player并沒有執行start(),后面生成player都會在prefetch()和start()的時候產生上面的異常! 因為我有一個midi player一直在prefetch狀態,所以新生成的midi的player都不能start(). 真是個奇怪的現象阿,在其他手機上都不會有這個問題。” ---saltedfish |
| ? | ? |
?
8?混音問題
?
player/mixer
| 關鍵詞 | 詳細描述 | |
| Moto真機上如何在播放背景音樂的時候再播放音效? | “摩托羅拉V300-V500-V600同時播放音樂的講究: 唯一支持的同步播放音樂的辦法是,midi和wav聲音混合播放。 即使是這樣,也存在著一個限制: 應用程序必須先播放midi(可以作為背景音樂),然后再播放wav;wav文件還必須是以下的格式: PCM 8000KHZ; 8Bit; Mono。 除了上面這種方法,只要是一個新的media被播放,上一個Player必須被停止而且釋放資源。” --moto文檔 ? “MOTO系列手機中JAVA程序播放一個聲音文件比較簡單,但是用于交互式音效時就有問題了。 根據MOTO的一些資料顯示,在MOTO手機中播放聲音有下面幾條約束: 1、除了同時播放一個MIDI和一個WAV以外,MOTO手機無法同時播放多個聲音,而且必須是先播放MIDI然后播放WAV; 2、除了MIDI或音階序列以外,不能同時實現player的多個實例進入prefetched狀態(預讀取聲音流); 3、播放新的聲音之前,前一個player必須停止并釋放資源(stop();deallocate())。 如果你遇到以下問題,可以試試我的解決方法: 1)只能播一次,或幾次,接著就無法發出聲音; 2)播放新的聲音時,總是會多播放一次前一個聲音。” ---linchangyu | |
| nokia6230i上的MediaException現象 | “當一個Player被prefetched,那么其他Player也就不再能夠prefetched,除非它們都是midi或都是amr。 如果你沒有在start/prefetch一個Player之前把其他的Player停下來,那么你將得到一個MediaException。” --?無名 ? | |
9?CustomItem問題
?
CustomItem/repaint/traverse
| 關鍵詞 | 詳細描述 | |
| CustomItem的repaint | “repaint()產生重繪事件,在CustomItem里它有兩個同名的方法,其中一個有四個參數,用來指定重畫區的起始X、Y坐標,寬度和高度;另外一個沒有參數,表示重畫CustomItem的整個區域。paint()方法里的后兩個參數也是寬度和高度,但是這兩個方法的寬度和高度沒有任何聯系,?paint方法里的W和H是Item內容區域的寬度和高度,并且只有這兩個值大于0時,paint()方法才會被調用。” --mydeman ? “repaint()被調用之后會立刻返回,而調用paint()回調函數的工作會有另外一個專門處理UI的線程來完成。因此如果希望得到paint()方法完成后再返回,那么就可以在repaint()之后立刻調用serviceRepaint(),來強制隊列中重繪事件快點完成。” --- mydeman | |
| CustomItem上處理過左右上下方向鍵 | “由于我的CustomItem控件和一個Gauge控件同處于一個Form上,所以按上下左右鍵的時候,實際上被Form處理了,Form就認為上下左右鍵是在切換控件的焦點,而不會把這個按鍵事件傳給我的CustomItem了。也就是說,我的寫法一樣不會得到上下左右鍵的按鍵事件。” --?zhengyun ? “一部手機是否實際支持CustomItem internal traversal,需要向getInteractionModes()方法查詢才可知道,因為這是隱含的策略,并不是一定的。聽說,在Nokia真機上,traverse好像并不好使用。 在我這里,這段代碼在模擬器上能夠使用,在真機上我不敢保證: ? 以下內容為程序代碼: ?????protected boolean traverse(int dir,int viewportWidth, ????int viewportHeight,int visRect_inout[]) ??{ ??????????System.out.println("Enter traverse"); ? ?????????if(dir == Canvas.UP){ ???????System.out.println("traverse>>Press Up key!"); ??????????????return true; ??????????}else if(dir == Canvas.DOWN){ ?????System.out.println("traverse>>Press Down key!"); ??????????????return true; ??????????}else if(dir == NONE){ ?????System.out.println("traverse>>Press None key!"); ??????????????return true; ??????????} ? ??????????return false; ??} ?????protected void traverseOut(){ ?????????System.out.println("Enter traverse out"); ?????}” --?zhengyun ? “protected boolean traverse(int dir, int viewportWidth, int viewportHeight,???int[] visRect_inout) { ? ??switch (dir) { ??case Canvas.DOWN: ???if (location == UPPER) { ????location = IN; ???} else { ????repaint(); ????location = LOWER; ????return false; ???} ???break; ? ??case Canvas.UP: ???if (location == LOWER) { ????location = IN; ???} else { ????repaint(); ????location = UPPER; ????return false; ???} ???break; ? ??case Canvas.LEFT: ???System.out.println("LEFT"); ???break; ??case Canvas.RIGHT: ???System.out.println("RIGHT"); ???break; ??} ??return true; } 實際上在FORM里的左右鍵事件,也被用來處理焦點,只不過在CUSTOM ITEM里左右鍵沒有響應,用上下鍵來處理焦點事件了。” ---hebaochen | |
?
10 Nokia播放Tone音樂問題
?
Sound/
| 關鍵詞 | 詳細描述 | |
| 按鍵,音樂被中斷 | “在Nokia 3650,7650上使用Tone播放聲音,如果用戶一按鍵,那么音樂馬上被中斷。這個問題是已經在Nokia官方開發論壇上得到確認。是Symbian 6.0系統上的一個bug,在Symbian 7.0系統的手機(Nokia 7610,6600)上沒有這個問題,在Nokia 40上也沒有這個問題。 解決之道:這是系統的bug,只有使用其它方式的音樂播放,比如midi格式音樂,否則是沒有辦法的。” --二當家的 ? ? | |
總結
以上是生活随笔為你收集整理的j2medev“用户界面和多媒体”版面问题整理[0407更新]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 终于拿到了ThinkPad T61笔记本
- 下一篇: Visual Studio是蝙蝠车,LI