zoukankan      html  css  js  c++  java
  • 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  直接用nokiaFullCanvas,可以全屏176 x 220

    k700cmidp2.0的那个this.setFullScreenMode(true);也是可以全屏的,176x220

    k700c直接用nokiaFullCanvas全屏好像是176*208,直接拿nokia60上的程序可以直接放进去。键值和60的也是相同的,只是多了一个返回键,我忘了值是多少了。用2.0GameCanvas大小是176*220

    --- lulei204

     

    不使用FullCanvas实现全屏的方法

    为了用标准的SUN WTK2.1开发能兼容各种机型的MIDP2.0游戏,会遇到一个奇怪的全屏问题,在K700上好好的,到了Nokia上居然死活显示一半,费了一番功夫后,终于不用FullCanvas实现了兼容K700Nokia的全屏显示,方法如下:

    在索爱的K700上,实现全屏很简单,如下写法就可以了:

    public Canvas1()

    {         super(false);

            this.setFullScreenMode(true);

            this.width=getWidth();

            this.height=getHeight();

    } 得到的屏幕大小是176*220

    Nokia上就比较奇怪了,这种方式取得的widthheight居然是176*144

    需要加以下代码修正一下:

    if(width>=176)

    {     if(height<208)

        {

             height=208;

        }

    } 绘图部分都以widthheight为基准。

    另外canvas1不能继承系统的GameCanvas,因为系统GameCanvas里的缓冲图还是176*144的,画出来就只能是半屏,我用j2me polish里的GameCanvas修改一下后,放到src里代替系统GameCanvasOK了。

    修正过的GameCanvas代码如下:

    http://www.j2medev.com/bbs/dispbbs.asp?

    BoardID=19&ID=3218&replyID=&skin=1

    ---alexhy

    FullCanvassetFullScreenMode()的区别

    setFullScreenMode用于MIDP2.0设备上。com.nokia.mid.ui.FullCanvasNokia UI API 1.1的包,用于MIDP2.0设备上,SonyEricsson手机也支持。

     

    FullCanvas是肯定可以实现全屏幕显示的,但是MIDP2.0里面的setFullScreenMode()只是实现为尽量使用最大的屏幕空间,但是不一定是全屏幕,要看各个手机的实现。”

    ---mingjava

    FullCanvas不能加CommandsetFullScreenMode(true)可以加上Command()。只是我加上一个按键时,却不管把它设在哪里,只能是右键响应。”

    ---风过留痕

    FullCanvasCanvasGameCanvas分别有什么不同

    FullCanvasCanvas的子类,实现全屏的功能,而且把按键针对nokia的手机进行了映射。其他没有什么区别。”

    ---migjava

    GameCanvas也是Canvas的子类,自MIDP2.0起提供,专门针对游戏增加了一些功能。在按键和显示各方面的运用都和Canvas有较大的不同。”

    ---efei

    MotorolaMIDP1.0手机

    motorola如果不支持MIDP2.0,应该就没办法实现全屏了。全屏下的菜单很好实现,不用搞得象Command那么复杂,那个Command用起来就是很不爽,还是自己写最好。”

    ---海标

    Nokia S60全屏后的Canvas高度

    “canvas. setFullScreenMode(true)后,一定让他被绘制一次,系统会调用sizechange(int w,int h)wh肯定是全屏的。仅调用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全屏情况下getHeightBUG,此函数出自于

              * 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 ImageByteArray转换问题

     

    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就是AlphaRR就是RedGG就是GreenBB就是Blue

     

    还有一句话概括的:

    [quote]444,表示图形格式,好像Nokia S40的机器都是采用444格式表示RGB颜色的。就是红,绿,蓝各用4位表示,至于可以表示透明色ARGB4444格式,应该是机器硬件实现的。[/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.0getRGB()跟NOKIAgetPixels)是类似的。

    --- 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个字左右。

    用了FontSIZE_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中都无效。这是S60bug

    ---蜡笔小刀

     

    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的代码在k7006600上都没问题,在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的机器不能同时有两个midiplayerprefetch()中,即使前面那个player并没有执行start(),后面生成player都会在prefetch()start()的时候产生上面的异常!

    因为我有一个midi player一直在prefetch状态,所以新生成的midiplayer都不能start().

    真是个奇怪的现象阿,在其他手机上都不会有这个问题。”

    ---saltedfish

     

     

     

    8 混音问题

     

    player/mixer

    关键词

    详细描述

    Moto真机上如何在播放背景音乐的时候再播放音效?

    “摩托罗拉V300-V500-V600同时播放音乐的讲究:

    唯一支持的同步播放音乐的办法是,midiwav声音混合播放。

    即使是这样,也存在着一个限制:

    应用程序必须先播放midi(可以作为背景音乐),然后再播放wavwav文件还必须是以下的格式:

    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现象

    “当一个Playerprefetched,那么其他Player也就不再能够prefetched,除非它们都是midi或都是amr

    如果你没有在start/prefetch一个Player之前把其他的Player停下来,那么你将得到一个MediaException。”

    -- 无名

     


    9 CustomItem问题

     

    CustomItem/repaint/traverse

    关键词

    详细描述

    CustomItemrepaint

    repaint()产生重绘事件,在CustomItem里它有两个同名的方法,其中一个有四个参数,用来指定重画区的起始XY坐标,宽度和高度;另外一个没有参数,表示重画CustomItem的整个区域。paint()方法里的后两个参数也是宽度和高度,但是这两个方法的宽度和高度没有任何联系, paint方法里的WHItem内容区域的宽度和高度,并且只有这两个值大于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格式音乐,否则是没有办法的。”

    --二当家的

     

     

     

  • 相关阅读:
    Git修改注释
    数组和切片的区别
    SpringBoot启动报:Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
    eclipse中web.xml报:The content of element type "web-app" must match "(icon?,display- name?,
    eclipse错误: 在类xxx中找不到 main 方法, 请将 main 方法定义为: public static void main(String[] args) 否则 JavaFX 应用程序类必须扩展javafx.application.Application
    idea Cannot resolve method ‘setAttribute(java.lang.String, java.lang.String)/不能使用pageContext.setAttribute()
    解决Nginx启动报nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    数据仓库开发规范
    详解会话技术cookie、session和token
    Requests爬虫包及解析工具 xpath、正则、Beautiful Soup
  • 原文地址:https://www.cnblogs.com/zhengyun_ustc/p/j2medev_ui_multimedia_qas.html
Copyright © 2011-2022 走看看