J2meUI设计.docx

上传人:来看看 文档编号:5014934 上传时间:2020-01-28 格式:DOCX 页数:37 大小:372.34KB
返回 下载 相关 举报
J2meUI设计.docx_第1页
第1页 / 共37页
J2meUI设计.docx_第2页
第2页 / 共37页
J2meUI设计.docx_第3页
第3页 / 共37页
J2meUI设计.docx_第4页
第4页 / 共37页
J2meUI设计.docx_第5页
第5页 / 共37页
点击查看更多>>
资源描述

《J2meUI设计.docx》由会员分享,可在线阅读,更多相关《J2meUI设计.docx(37页珍藏版)》请在三一文库上搜索。

1、目录JavaME UI设计之Bitmap字体1JavaME UI设计之点阵字体5JavaME UI设计之图像特效8图像缩放9亮度、对比度10图片剪切11添加字符串12负片特效13黑白特效14粉笔画特效15蒙版特效17霓虹灯效果18JavaME UI设计之透明图片处理20JavaME UI设计之九宫格22JavaME UI设计之资源优化技巧24JavaME UI设计之低级界面文本控件27JavaME UI设计之滚动条31JavaME UI设计之渐变色处理33JavaME UI设计之Bitmap字体当我们使用 MIDP 的 Graphics 类,可以调用其 setFont() 来指定字体,然后调用

2、该字体的一种 drawChar() 或 drawString() 方法来在 canvas 或后台图像上呈现字体。MIDP 仅提供了一套有限的字体选项,但是:字体可以是等宽的或成比例的,大小可以是小、中或大,并且样式可以是平铺或粗体、斜体和下划线的任意组合。运行库实现工具可能没有满足您的标准的字体,它会将自由返回其确定的最相近的字体,而各种各样的应用程序通常需要使用各种符合应用风格的字体,这时我们就需要使用自定义字体,即需要自己来实现一个字体类;自定义字体通常有两种,分别是:Bitmap字体和点阵字体,本文我们主要分析如何实现一个Bitmap字体类,下一篇文章我们将介绍在J2ME上的点阵字实现。

3、Bitmap 字体的绘制指令是位到图形环境中的位置的逐一映射。bitmap 字体中的每一个字符对应于从内存拷贝到屏幕的像素排列。换一种说法,每一个字符是通过拷贝到屏幕的一个后台图像来绘制的。从这个角度看,立即就能得到字体的定义(包含用于呈现字体的指令的文件)本身就可以是一个压缩格式(如 PNG 或 JPEG)的图像文件。我们可以把这个图像读到内存中,然后在需要绘制我们的字体的字符时,将它的各有关部分拷贝到屏幕。那么要实现一个Bitmap 字体类的第一步就是要创建一个这样的图像。高度应当就是字体所需的高度,并且足够宽来容纳要呈现的字符集中的每一个字符。那是多宽呢?Java 技术通常采用 Unic

4、ode Character Standard。Unicode 字符集有 95,000 多个字符,比我们能提供的要多,并远远超出我们的需要!因此 MIDTerm 的 Telnet 协议的实现方式是基于 7 位 ASCII 字符集的基础上,该字符集只包含 128 个字符。因为 MIDTerm 需要等宽字体,文档宽度应为一个字符宽度的 128 倍。例如,如果每一个字符高为 12 像素宽为 10 像素,为容纳所有的 128 个字符,则需要高为 12 宽为 1,280 的图像。现在有了用于放置对应于 ASCII 代码 0 到 127 的 128 个位置。为了能查明哪个字符放到哪个空位中,可能需要 ASC

5、II 表 。请注意前 31 个字符是“控制字符”并且不能看到,可以保留为空白。本文的演示示例中我们使用了如下图片,作为Bitmap 字体的图像。大家可以看到该图片的前一部分是空的,什么也没有,原因前面已经解释过,这里就不在重复,下面我们开始构建这个自定义字体类。首先定义一些成员变量,代码如下所示:public class BitmapFont private int style;/*字体类型*/ private int size;/*字体大小*/ private int baseline;/*基线*/ private int height;/*单个字符高度*/ private int widt

6、h;/*单个字符宽度*/ private int color; private int bgcolor; private Image image;/* 返回一个自定义字体的对象 */ private Image srcimage; /省略不分.字体的类型我们同样可以使用系统提供的Font中的一个风格,主要包括粗体、斜体等,然后开始构建我们自定义的字体,这里可以采用和Font类一样的静态方法,代码如下:public static BitmapFont getFont(String inName, int inStyle, int inSize) Image i; String filename

7、= inName; try i = Image.createImage(filename); catch(Throwable t) return new BitmapFont(i, inStyle, inSize);private BitmapFont(Image inImage, int inStyle, int inSize) image = inImage; style = inStyle; size = inSize; /*计算字符需要显示的高度和宽度,图片的假设一共有128个字符*/ try srcimage=null; srcimage = Image.createImage(in

8、Image); height = image.getHeight(); width = image.getWidth() / 128; /*计算字符需要显示的最下面非背景色的坐标位置*/ baseline = calculateBaseline(); catch(Throwable t)getFont函数的第一个参数就是我们所准备Bitmap字体的图像文件,创建好图片之后,需要通过calculateBaseline()函数来计算字符需要显示的最下面非背景色的坐标位置,首先假设图片上有128个字符,具体的计算实现代码如下:/*计算字符需要显示的最下面非背景色的坐标位置*/private int

9、calculateBaseline() int result = height; int imageWidth = image.getWidth(); int max = 0; int total; int row = new intimageWidth; int background; /*确定背景色,假设(0, 0)坐标的像素为北京颜色*/ image.getRGB(row, 0, 1, 0, 0, 1, 1); bgcolor = background = row0; /*按每行搜索像素*/ for(int y = height / 2;y height;y+) total = 0; i

10、mage.getRGB(row, 0, imageWidth, 0, y, imageWidth, 1); for(int x = 0;x max) max = total; result = y; return result;到这里就构建好了该字体类的,下面我们就可以开始实现字符的绘制了,绘制单个字符实际上就是使用setClip来设置裁剪区域,然后绘制将对应的字符在字体图像上的区域绘制在制定的裁剪区域内,具体绘制代码如下:private void drawCharInternal(Graphics g, char character, int x, int y, int anchor) /*

11、绘制倾斜类型的字体*/ if(style & Font.STYLE_ITALIC) != 0) g.setClip(x + 1, y, width, height / 2); g.drawImage(image, x - width * character + 1, y, anchor); g.setClip(x, y + height / 2, width, height / 2); g.drawImage(image, x - width * character, y, anchor); /*绘制加粗类型的字体*/ if(style & Font.STYLE_BOLD) != 0) g.s

12、etClip(x, y, width, height / 2); g.drawImage(image, x - width * character + 2, y, anchor); g.setClip(x, y + height / 2, width, height / 2); g.drawImage(image, x - width * character + 1, y, anchor); else /*绘制正常类型的字体*/ g.setClip(x, y, width, height); g.drawImage(image, x - width * character, y, anchor

13、); if(style & Font.STYLE_BOLD) != 0) g.drawImage(image, x - width * character + 1, y, anchor); /*绘制下划线的字体*/ if(style & Font.STYLE_UNDERLINED) != 0) g.drawLine(x, y + baseline + 2, x + width, y + baseline + 2); 绘制过程会根据Font.STYLE_ITALIC、Font.STYLE_BOLD、Font.STYLE_UNDERLINED等常量来确定字体的风格,包括粗体、斜体、下划线,绘制斜体

14、可以通过绘制两次相同的字符并将其绘制的x坐标偏移一个像素来实现,粗体则需要将两次绘制的x,y坐标都偏移一个像素,下划线风格则更加简单,在字体显示之后再绘制一条直线即可。通过drawCharInternal函数,我们就可以实现类似于Font中的drawchar、drawchars、drawString等函数了,下面我们列举出一个绘制字符和字符数组的函数,如下:public void drawChar(Graphics g, char character, int x, int y, int anchor) int clipX = g.getClipX(); int clipY = g.getCl

15、ipY(); int clipW = g.getClipWidth(); int clipH = g.getClipHeight(); /*使用setClip方式绘制单个字符到屏幕上*/ drawCharInternal(g, character, x, y, anchor); g.setClip(clipX, clipY, clipW, clipH);/*画字符数组*/public void drawChars(Graphics g, char data, int offset, int length, int x, int y, int anchor) if(anchor & Graphi

16、cs.RIGHT) != 0) x -= charsWidth(data, offset, length); else if(anchor & Graphics.HCENTER) != 0) x -= (charsWidth(data, offset, length) / 2); /*判断需要绘制的字体位置*/ if(anchor & Graphics.BOTTOM) != 0) y -= height; else if(anchor & Graphics.VCENTER) != 0) y -= height / 2; /*保存原来的裁减区数据*/ int clipX = g.getClipX

17、(); int clipY = g.getClipY(); int clipW = g.getClipWidth(); int clipH = g.getClipHeight(); char c; for(int i = 0;i length;i+) c = dataoffset + i; drawCharInternal(g, c, x, y, Graphics.TOP | Graphics.LEFT); x += width; /*在裁减区绘制*/ g.setClip(clipX, clipY, clipW, clipH);原理很简单了,直接通过循环调用drawCharInternal函数

18、来绘制出每一个字符即可,drawString就只需要将字符串通过toCharArray函数将字符串转换为字符数组即可。最后测试一下该自定义自体类的使用,代码如下:BitmapFont ft = BitmapFont.getFont(/font.png, Font.STYLE_ITALIC, 256);ft.setColor(0xffff0000);ft.drawString(g,str, 0, 0, Graphics.LEFT|Graphics.BOTTOM);效果如下:到这里一个自定义字体类基本完成,当然,稍作扩展还可以设置字体的颜色,背景颜色等,由于篇幅关系,这里不能将所有代码都贴出来了!

19、另外,这种字体仅适合于绘制英文的字符串,要是做英文应用,可以很好的使用,但是并不支持中文,下一篇文章我们将介绍另一种自定义字体的实现,它将能支持中文的显示。JavaME UI设计之点阵字体上一篇文章中我们介绍了在JavaME中实现Bitmap字体,但是要想通过Bitmap字体来显示中文几乎不太可能,除非你中文很少,也不介意这样做浪费时间,如果你想显示中文,又不想使用JavaME本身提供的字体,那么可以考虑使用点阵字,这就是本文将要给大家介绍的,如何在JavaME中使用点阵字库。要在JavaME中使用点阵字,首先需要了解什么是点阵字,可以到各大百科互动网站找到相关介绍,这里就不耽误大家的时间了,

20、点阵字实际上就是用画点的方式画出一个字。比如一个16*16的点阵字,它的每一个点占一位,一共是16*16,那么一个16的字所占大小是32byte。需要明白点阵字体优点是显示速度快,不像矢量字体需要计算;其最大的缺点是不能放大,一旦放大后就会发现文字边缘的锯齿,因此如果需要显示不同大小的点阵字,就需要准备不同大小的点阵字库。点阵字库的制作方法也非常简单,网上有很多方法,本文我们选择使用HZK16字库来演示在JavaME如何使用点阵字库。HZK16字库是符合GB2312标准的16 16点阵字库,HZK16的GB2312-80支持的汉字有6763个,符号682个。其中一级汉字有3755个,按声序排列

21、,二级汉字有3008个,按偏旁部首排列。我们在一些应用场合根本用不到这么多汉字字模,所以在应用时就可以只提取部分字体作为己用。HZK16字库里的1616汉字一共需要256个点来显示,也就是说需要32个字节才能达到显示一个普通汉字的目的。 我们知道一个GB2312汉字是由两个字节编码的,范围为A1A1FEFE。A1-A9为符号区,B0到F7为汉字区。每一个区有94个字符(注意:这只是编码的许可范围,不一定都有字型对应,比如符号区就有很多编码空白区域)。下面以汉字“我”为例,介绍如何在HZK16文件中找到它对应的32个字节的字模数据。前面说到一个汉字占两个字节,这两个中前一个字节为该汉字的区号,后

22、一个字节为该字的位号。其中,每个区记录94个汉字,位号为该字在该区中的位置。所以要找到“我”在hzk16库中的位置就必须得到它的区码和位码。区码:区号(汉字的第一个字节)-0xa0(因为汉字编码是从0xa0区开始的,所以文件最前面就是从0xa0区开始,要算出相对区码)位码:位号(汉字的第二个字节)-0xa0这样我们就可以得到汉字在HZK16中的绝对偏移位置:offset=(94*(区码-1)+(位码-1)*32有了偏移地址就可以从HZK16中读取汉字编码了,下面我们就需要在JavaME中构建一个能够读取和显示点阵字库文字的类CustomFont,首先将我们准备的点阵字库HZK16放入工程的re

23、s文件夹中,并在CustomFont中标出该字库的路径和编码的等信息,如下代码所示。public class CustomFont public final static int mask = 128, 64, 32, 16, 8, 4, 2, 1 ; public final static String ZK_PATH = /HZK16; public final static String ENCODE = GB2312; /.要读取一个汉字,我们首先要读取出汉字的区位码,通过如下代码可以读取出汉字的区位码:/*获得文字的区位码*/protected int getByteCode(Str

24、ing str) int byteCode = new int2; try byte data = str.getBytes(ENCODE); byteCode0 = data0 0 ? 256 + data0 : data0; byteCode1 = data1 0 ? 256 + data1 : data1; catch (Exception ex) return byteCode;然后通过区位码在字库中去查找文字信息,具体实现代码如下:/*读取文字信息* param areaCode* 区码*param posCode* 位码*return 文字数据*/protected byte re

25、ad(int areaCode, int posCode) byte data = null; try int area = areaCode - 0xa0;/ 获得真实区码 int pos = posCode - 0xa0;/ 获得真实位码 InputStream in = getClass().getResourceAsStream(ZK_PATH); long offset = 32 * (area - 1) * 94 + pos - 1); in.skip(offset); data = new byte32; in.read(data, 0, 32); in.close(); cat

26、ch (Exception ex) return data;能从字库中读取出点阵字的信息,下面就是将这些数据绘制出来即可,绘制函数如下所示。/*绘制点阵中文汉字,gb2312,16字* param g* 画笔*param str* 需要绘制的文字*param x* 屏幕显示位置x*param y* 屏幕显示位置y*param color* 文字颜色*/protected void drawString(Graphics g, String str, int x, int y, int color) byte data = null; int code = null; int byteCount

27、;/ 到点阵数据的第几个字节了 int lCount;/ 控制列 g.setColor(color); for (int i = 0; i str.length(); i+) if (str.charAt(i) 0x80) / 非中文 g.drawString(str.substring(i, i + 1), x + (i 4), y, 0); continue; code = getByteCode(str.substring(i, i + 1); data = read(code0, code1); byteCount = 0; for (int line = 0; line 16; li

28、ne+) lCount = 0; for (int k = 0; k 2; k+) for (int j = 0; j 8; j+) if (databyteCount & maskj) = maskj) g.drawLine(x + lCount + (i 4), y + line, x + lCount + (i 4), y + line); lCount+; byteCount+; 完成了点阵字的读取和绘制操作,下面我们通过:mCustomFont.drawString(g, 测试点阵字库的显示!好看多了。, 0, 20, 0xff0000);来测试该自定义点阵字库在JavaME中的使用

29、 ,效果如下图所示。显示肯定没有问题,但是我们开发出来的应用程序包也就随之增加了很大,主要包括HZK16字库文件,另外,在使用过程中所需要消耗的内存也增加,因为一个16*16的汉字就需要32个字节,因此,对于应用中汉字较少的,可以采用自己制作出一些特定的点阵字的数组,然后进行绘制,可以节省不少空间。关于JavaME中字体的处理就介绍到这里,几乎介绍了JavaME中所有与字体相关的内容,足以解决JavaME中大部分文字显示的难题了。JavaME UI设计之图像特效通常在做应用时,需要实现图像的部分特效,最简单的方式可以通过美术制作出各种特效的图片,然后用程序来显示即可,但是这样做出来的程序包会很

30、大,而且很浪费内存空间,因此我们需要通过程序来操作图像的每一个像素信息,从而实现各种图片特效,本文就主要针对一些常用的特效进行实现。在开始具体的特效实现之前,我们需要分析一下MIDP2.0中的getRGB(.) 函数,该函数可以将image的alpha以及RGB值转换为一个int数组。 我们可以用该方法以及获得的数组改变图片的alpha,r,g,b值。该函数原型如下:public void getRGB(int rgbData, int offset, int scanlength, int x, int y,int width,int height);在J2me 里的int是4 bytes的

31、,image中的每个像素以ARGB值的方式描述,每个值可以为0-255。 如果 alpha 值为 0, 对应的像素就为透明,反之如果alpha 值为255, 像素为完全不透明。 其中返回的rgbData不一定和源图像的实际颜色一致,所有的颜色都可能经过重新采样,以适应当前的显示设备的颜色性能,例如,在黑白手机上(现在几乎没有了),所有的红、绿、蓝像素都将被相应的灰度值所替代。在不支持Alpha通道的设备上,所有的不透明像素的Alpha值都被设成0xFF(全透明),其他象素的Alpha值都被设成0x00。在支持Alpha通道的设备上,Alpha值同样有可能经过重新采样,以适应当前设备所支持的半透

32、明级数。另外,scanlength定义了数组的扫描宽度,为了避免数据的交叠,其绝对值必须大于或者等于参数width。(x,y)是图像区域的左上角坐标,width和height分别是所截取图像区域的宽度和高度,以像素为单位。首先,我们先准备一下两个函数:/*获取图片RGB数据,并返回大小为图片的width*height大小的一维数组*/public int getPixels(Image src) int w = src.getWidth(); int h = src.getHeight(); int pixels = new intw * h; src.getRGB(pixels, 0, w,

33、 0, 0, w, h); return pixels;/*将pixels里的数据,生成一张图片,图片宽为w,高为h*/public Image drawPixels(int pixels, int w, int h) Image image = Image.createRGBImage(pixels, w, h, true); pixels = null; return image;其中getPixels用于从一个Image中获取像素信息,保存到一个int数组中,后面的各种图像特效都将来处理这个int数组,而drawPixels函数则用于将一个int数组转换一个Image对象,通常用于将一个

34、处理之后的int数组合成一个图像用。在开始使用特效之前,我们先看一下准备好的冤死图片如下图所示。图像缩放图像缩放算法也很多,这里我们介绍一个比较简单,效果也比较好的算法,其原理就是将图片转换为int数组,然后按照缩放的比例从原图片中对应的比例中取得像素信息即可,具体实现代码如下:/* 调整图片大小destW 调整后的宽,destH调整后的高*/public Image effect_resizeImage(Image src, int destW, int destH) int srcW = src.getWidth(); int srcH = src.getHeight(); int des

35、tPixels = new intdestW * destH; int srcPixels = getPixels(src); for (int destY = 0; destY destH; +destY) for (int destX = 0; destX destW; +destX) int srcX = (destX * srcW) / destW; int srcY = (destY * srcH) / destH; destPixelsdestX + destY * destW = srcPixelssrcX + srcY * srcW; return drawPixels(des

36、tPixels, destW, destH);原图片的宽度和高度为240*99,我们通过该函数将其缩放为120*50之后效果如下图所示。亮度、对比度要改变一个图片的亮度和对比度实际上可以通过该百年每个像素的r,g,b颜色值来实现,如果原始值为r,g,b按照对比度c和亮度l改变之后的值为r*c+l,g*c+l,b*c+l即可。最后需要判断每个值是否超过255,如果大于255,则为255。具体实现代码如下:/* 调整图片亮度与对比度。 contrast 对比度,light 亮度*/public Image effect_light_contrast(Image src, double contra

37、st, int light) int srcW = src.getWidth(); int srcH = src.getHeight(); int srcPixels = getPixels(src); int r = 0; int g = 0; int b = 0; int a = 0; int argb; / 公式y =ax+b a为对比度,b为亮度 / int para_b = light - 127 * (light - 1); for (int i = 0; i srcH; i+) for (int ii = 0; ii 24); / alpha channel r = (argb

38、& 0x00ff0000) 16); / red channel g = (argb & 0x0000ff00) 8); / green channel b = (argb & 0x000000ff); / blue channel r = (int) (r * contrast + light); g = (int) (g * contrast + light); b = (int) (b * contrast + light); if (r 255) r = 255; else if (r 255) g = 255; else if (g 255) b = 255; else if (b 0) b = 0; srcPixelsi * srcW + ii = (a 24) | (r 16) | (g 8) | b); return drawPixels(srcPixels, srcW, srcH);使用该函数调整亮度和对比度(effect_light_contrast(mImage,3,20))的效果如下图所示,图片剪切图片剪切在MIDP2.0中已经提供了api,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 研究报告 > 商业贸易


经营许可证编号:宁ICP备18001539号-1