LWUIT 组件的简单介绍

来源:互联网 发布:ip网络电话软件 编辑:程序博客网 时间:2024/05/01 02:38

 

在MIDlet中初始化Lwuit 也是唯一使用原有J2me的东西

可以在startApp方法中定义启动的过程
  public void startApp() {
      //init the LWUIT Display
      Display.init(this);
      //加载资源文件
try {
Resources r = Resources.open("/myresources.res");
UIManager.getInstance().setThemeProps(r.getTheme(
r.getThemeResourceNames()[0])
);
} catch (java.io.IOException e) {
}
简单的使用一个内置Form进行显示,而无须使用一个而外的类
   Form f = new Form();
   f.setTitle("Hello World");
   f.setLayout(new BorderLayout());
   f.addComponent("Center", new Label("I am a Label"));
   f.show();
注意使用show方法进行显示


组件介绍

Component 用于显示到页面上的基础部分,可以理解为DisplayObject

,也就是组件部分

Container 用于保存多个Components的容器类型,提供了布局的能力


Form : 提供title和menus,并且提供一个content放置Components,并且提供了

content的滚动能力
       addComponent,用于添加Components到Content中

提供的一些方法和使用方式

Form mainForm = new Form("Form Title");  //声明一个带标题的Form

mainForm.setLayout(new BorderLayout()); //设置布局管理器

mainForm.addComponent(BorderLayout.CENTER, new Label(“Hello,World”)); //添加Components组件,

mainForm.setTransitionOutAnimator(CommonTransitions.createFade(400)); //设置动画

mainForm.addCommand(new Command("Run", 2)); //添加菜单命令

mainForm.show(); //显示Form

一些技巧 
1:可以使用带参数的构造函数,设置标题.也可以不设置标题的构造函数
2:addComponent() 方法提供两个重载,区别在于是否指定布局位置
3:Transition动画用于在forms之间进行切换时候触发
4:Form通过Commands添加菜单,根据添加顺序排序显示,其他使用与普通的

J2me一样


Label: 可以同时显示图片和文字,设置align布局,可以通过继承Label实现扩展,如果更复杂,可以使用Button

提供的一些方法和使用方式

Label textLabel = new Label("I am a Label");  //创建一个单行文本

Image icon = Image.createImage("/images/duke.png");
Label imageLabel = new Label(icon);   //创建一个带图片的Label

setTextPosition(int alignment); //设置布局方式,CENTER, LEFT, RIGHT,LEFT,TOP, BOTTOM, LEFT, RIGHT,


Button 可以用于触发一个点击的事件Action,使用一个ActionListeners 进行监听

final Button button  = new Button("Old Text");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
button.setText("New Text");
}});   //使用匿名的ActionListener接口实现类进行监听

Button继承Label, 所以可以设置不同图文混编的风格,并且提供了三种状态ollover, pressed, and the default
state


RadioButton  单选按钮,继承自Button

RadioButton radioButton = new RadioButton(“Radio Button”);
同样,也会触发action

ButtonGroup 用于保证RadioButton只能选中一项

RadioButton rb1 = new RadioButton("First RadioButton in Group 1");
RadioButton rb2 = new RadioButton("Second RadioButton in Group 1");
ButtonGroup group1 = new ButtonGroup();
group1.add(rb1);
group1.add(rb2);

exampleContainer.addComponent(rb1);
exampleContainer.addComponent(rb2);

这里需要注意,只需要添加addComponent(RadioButton) 到容器中,不需要添加ButtonGroup,只用于后台管理


CheckBox  多选框,不需要添加到group中,同样也触发事件

final CheckBox checkBox = new CheckBox(“Check Box”);

通过checkBox.isSelected() 判断是否被选中

ComboBox  列表,只允许一个被选中,多用于空间有限时候提供多选项的单选功能

创建需要一个数组作为数据源
String[] content = { "Red", "Blue", "Green", "Yellow" };
ComboBox comboBox = new ComboBox(content); //创建一个Combox,在这个构造函数中也是使用List实现

comboBox.setListCellRenderer(new checkBoxRenderer()); //设置renderer 渲染器
也可以使用addActionListener注册事件


通过实现不同的renderer接口可以给组件提供不同的显示效果 implements ListCellRenderer


TextArea

例子
TextArea textArea = new TextArea(5, 20, TextArea.NUMERIC);
textArea.setEditable(false);

构造函数的前两个参数为 总行数和单行长度,第三个参数用于传递到本地文本输入,用于指定限制的类型

可以使用TextArea的常量 ANY,EMAILADDR, NUMERIC, PHONENUMBER, URL, or DECIMAL,PASSWORD, UNEDITABLE, SENSITIVE,NON_PREDICTIVE, INITIAL_CAPS_SENTENCE, INITIAL_CAPS_WORD.也可以使用 | 设置复合约束
默认下可编辑


TabbedPane   通过类似Tab的选项卡方式并排放置一组容器,容器的tab标签可以使用图文混编方式

可以使用addTab or insertTab methods 方法添加容器
removeTabAt(int index) 移除容器
tab的索引由0开始

tab标签可以有四种不同的放置方法  LEFT, RIGHT, TOP or BOTTOM using the setTabPlacement method.

TabbedPane tabbedPane = new TabbedPane(TabbedPane.TOP);
tabbedPane.addTab("Tab 1", new Label("I am a TabbedPane!"));
tabbedPane.addTab("Tab 2", new Label("Tab number 2"));

构造函数使用一个Tab标签布局的常量作为参数

addTab,第一个为tab标签名,第二个参数为直接放置到容器中的内容

Using Lists

List,使用Swing的  MVC模式进行创建
rendered using a ListCellRenderer and are extracted using the ListModel.

使用ListCellRenderer 作为显示的V 
使用ListModel. 作为数据源M
其他部分为C进行操作

创建List 有四个构造函数
List()           
List(ListModel model)   //直接实例化ListModel
List(Object[] items) //Array数组
List(Vector items) //Vector集合

ListModel  也可以分为自定ListModel的实现,以及DefaultListModel

DefaultListModel的使用
String[] items = { "Red", "Blue", "Green", "Yellow" };
DefaultListModel myListModel = new DefaultListModel(items);  //使用Array作为数据源

ListCellRenderer 渲染器
同样也可以自定ListCellRenderer的实现,以及DefaultListCellRenderer

自定义的时候,可以通过继承Libel,来节约开发的速度 ,主要实现两个方法
public class MyYesNoRenderer extends Label implements ListCellRenderer{
public Component getListCellRendererComponent(List list,
Object value, int index, boolean isSelected) {
((Boolean)value).booleanValue()  来获取单项的值
}

public Component getListFocusComponent(List list) {
Label label = new label("");
label.getStyle().setBgTransparency(100);
return label;
}}


DefaultListCellRenderer,默认也是使用Label and the ListCellRenderer interface.
实现两个方法,大体和上面相同
getListCellRendererComponent()
getListFocusComponent()  //选中风格,可以通过修改透明度来表现


添加或移除item

添加的方法有两种,创建一个ListModel,然后add到list中,重置一个List 使用setModel(ListModel model). 方法

移除的方法有removeItem(int index) or removeAll() methods.

myListModel.addItem(“New Item”); //添加Item
myListModel.removeItem(index);   //删除Item
myListModel.removeAll(); //删除所有Item

List 事件 提供了两种事件 ActionEvent and SelectionsListener
addFocusListener(FocusListener l) 区别于常用的Action
SelectionListener 应该会更有用一些

Fixed Selection Feature 应该是只有一行的List,不弹出菜单的模式 //具体还是demo才知道
通过 setFixedSelection(int fixedSelection) 进行设置
通过四个常量属性进行设置
FIXED_NONE   //普通的List
FIXED_TRAIL  //静态
FIXED_LEAD   // ...下面两种都需要用demo看下区别
FIXED_CENTER

setSmoothScrolling(true) //设置这个属性,应该是在移动时增加动画效果,默认为false


Using Dialogs 对话框

也提供一个Content,可以存放其他的Components  //对于是否阻塞线程,需要了解一下

Dialog提供了五种不同的类型,默认附加了不同的提示音
ALARM //警告
CONFIRMATION //确认
ERROR //错误
INFO //信息
WARNING //警告提示 

当前默认情况下不支持Icon,不过可以自定义Dialog

调用dialog的show()方法进行显示,提供的参数很多,可以选择合适的重载进行显示
1:String title  标题
2:Component body 一个单独的Component
3:String text 用于代替Component body部分
4:Command[] cmds 可以添加Commands
5:int type 设置不同的类型
6:Image icon 添加icon
7:timeout 打开持续时间,设置成0表示为持续打开
8:Transition transition 添加动画
9:String okText 设置Ok按钮的内容
10:String cancelText 设置cancel的内容
11:int top 设置top所在位置
12:int bottom 设置bottom位置
13:int left  同上
14:int right 同上
15:boolean includeTitle  //需要了解下

show方法可以返回三个类型 void,Command,boolean
boolean值在点击ok时为true, cancel时为null

使用非静态的方法显示Dialog
dialog.show(90, 90, 10, 10, true);

关闭dialog  dispose()
需要先show之前设置timer去关闭dialog

Dialog也可以返回一个Command 区别于点击OK按钮


Using LayoutManagers 使用布局管理器

已经的布局管理器
BorderLayout
BoxLayout
FlowLayout
GridLayout
GroupLayout

BorderLayout 边框布局模式(东西南北中)

如下五个区域
Center
East
North
South
West

在添加Components的时候进行设置
addComponent(BorderLayout.CENTER, component) // preferred
或者直接使用字符串
addComponent(“Center”, component) // valid but error prone  容易出错

BoxLayout  盒子布局
包括了 X_AXIS(横向)  Y_AXIS(竖向)的布局,并排的方式

BoxLayout boxLayout = new BoxLayout(BoxLayout.X_AXIS);
BoxLayout boxLayout = new BoxLayout(BoxLayout.Y_AXIS);

FlowLayout 流式布局
这个也是容器默认的布局方式
横向布局,如果长度超出,则自动换行处理

FlowLayout exampleLayout = new FlowLayout();
container.setLayout(exampleLayout);

也可以通过设置构造函数,用于设置布局起始的位置,比如 Left, Right, or Center
FlowLayout exampleLayout = new FlowLayout(Component.RIGHT);

GridLayout 表格式布局,可以用于设置九宫图

可以定制行和列,
GridLayout exampleLayout = new GridLayout(0,2);  //2表示每行显示两个单元格cell,0不知道是啥

GroupLayout  // GUI builders 的方式进行布局,用于NetBeans中的Swing开发


Using Painters

是一个接口,可以用于绘制一个Components的背景,将绘制在Components限定的范围内

如果要查看painter绘制结果,需要设置对应的transparency //需要查看下

painter可以使用绝对坐标的绘图,所以可以重用在其他组件之上

Painter diagonalPainter = new Painter() {
public void paint(Graphics g, Rectangle rect) {
g.drawLine(rect.getX(),
rect.getY(),
rect.getX() + rect.getSize().getWidth(),
rect.getY() + rect.getSize().getHeight());
}
};

注意查看这里获取位置的方法 x y, size width height

使用时候只要给指定的组件设置Painter即可
myComponent.getStyle().setBgPainter(diagonalPainter);
将会自动应用绘图

记得显示的调用设置透明度  0-255之间
myButton.getStyle().setBgTransparency(100);

Using the Style Object 设置样式对象

The Style object sets colors, fonts, transparency, margin, padding, images, and borders to define the style for a given component.

使用component.getStyle(). 获取该对象,可以在运行时候改变

颜色Style

Foreground color 前景色,主要指文字颜色
Foreground selection color 当组件获取焦点时,字体的颜色
Background color 背景色
Background selection color  获取焦点时候的背景色

这里颜色使用的是RGB(格式为0x000000),不带alpha透明色,有而外的透明设置在Style中

Font 字体

Transparency 透明度
setBgTransparency进行设置 范围是0-255之间

Margin and Padding 外边距和内间距,与css的盒模型一样

设置的方式
setPadding(int top, int bottom, int left, int right)
setPadding(int orientation, int gap)
setMargin(int top, int bottom, int left, int right)
setMargin(int orientation, int gap)

// orientation can be Component.TOP, BOTTOM, LEFT or RIGHT
这两个类型方法的区别在于同时设置一个属性,还是多个属性

Images  背景色,默认为不限制背景色  使用bgImage 可以用于进行设置

Borders边框类型

Style Listener 样式事件
myComponent.getStyle().addStyleListener(new StyleListener() {
public void styleChanged(String propertyName, Style source) {}
}}

Painters也可以用于在Style中设置样式,用于按照要求绘制背景
mycomponent.getStyle().setBgPainter(myPainter);


Theming 皮肤

refreshTheme()方法用于更新所有的样式,不过手动修改的样式元素,并不会被更新

设置样式属性需要注意的地方
Button.font – font for all buttons //将会作用到所有Button组件的字体
font- 将会影响到所有没有定义默认值的组components件
这里不像css那样有特殊的单独样式设置

所有支持的样式属性
fgColor   前景色 16进制的格式
bgColor   背景色 16进制的格式,也可以使用缩写ff
bgSelectionColor 背景选中色 16x
fgSelectionColor 前景选中色 16x
bgImage    背景图片
transparency  设置背景图样式透明色 0-255之间,不过目前对背景图无效

font 分为Bitmap font和System font 定义的方式为Bitmap{myFontName} 和System{face;style;size}
其中系统字体的参数为
face=FACE_SYSTEM,FACE_PROPORTIONALFACE_PROPORTIONAL
style=STYLE_PLAIN,STYLE_BOLD,STYLE_ITALIC
size=SIZE_MEDIUM,SIZE_SMALL,SIZE_LARGE
例如
System{FACE_SYSTEM;STYLE_PLAIN;SIZE_SMALL}

scaledImage      使用boolean值设置背景图使用平铺tiled还是重复scaled  默认为true,重复scaled

margin 外边距,使用四个参数进行设置,代表top, bottom, left, and right. For example, 1, 2, 3, 4

padding 内边距,使用与margin类似

更新主题时
使用Resources.open("/javaTheme.res");//进行加载
使用UIManager.getInstance().setThemeProps(r.getTheme(r.getThemeResourceNames()[0]));//进行设置
然后可以使用components.refreshTheme 更新组件的样式

LookAndFeel  DefaultLookAndFeel  似乎是用来定义一些样式无法修改到的东西,比如滚动条,具体要看API Documention

Resources 资源

LWUIT允许的resource elements的元素包括:
Image Resources       //图像资源
Animation Resources   //动画资源
Bitmap Fonts       //位图字体
Localization (L10N)   //本地化
Themes       //主题

可以通过专门的编辑器 Resource Editor 或者Ant tasks来创建Resources

Loading a Resource 读取一个资源文件
Resources res = Resources.open(“/myresourceFile.res”);
Image i = res.getImage(“imageName”);

图片可以保存在res文件中,或者直接放置在jar文件中

读取jar中图片的方式
Image image = Image.createImage("/images/duke.png");

image的标签,应该是res配置的时候,可以有三个属性
name //名称,默认为文件名
file //图像文件所在位置
pack //boolean值 ,默认为false ,用于设置是否为Indexed

图像少于256色的时候,可以使用Index image,有利于节约空间

使用indexed image的注意地方
1:因为需要按照像素的去操作图像,所以在显示的时候速度比较慢,不过在现在的手机上并不明显
2:在运行时转换indexed image将会比较慢,而且可能会失败,所以应该在编译时候进行转换
3:Indexed image并没有在res文件中被压缩,所以res文件看起来比较大,不过在jar文件中却能被很好的压缩,而且效果比使用png更好
4:indexed images  创建后将不能被改变,比如getGraphics(),详情看API

Animation Resources
LWUIT支持从Gif文件中得到动画效果,保存的结构类似image structure
StaticAnimation 用于操作动画..派生自Image,所以可以直接使用在icon或者其他地方

Fonts 字体
LWUIT支持bitmap fonts and system fonts.

System Font  包括了三个参数
Face   //如FACE_SYSTEM, FACE_PROPORTIONAL and FACE_MONOSPACE.
Style  //如STYLE_PLAIN, STYLE_ITALIC, STYLE_BOLD.
Size   //如SIZE_SMALL, SIZE_MEDIUM, SIZE_LARGE.

在类的内部可以去创建字体引用
Font.createSystemFont(Font.FACE_SYSTEM,Font.STYLE_BOLD,Font.SIZE_MEDIUM);

同时也可以去创建复合类型的字体(加粗和倾斜)
Font.createSystemFont(Font.FACE_SYSTEM,Font.STYLE_BOLD | Font.STYLE_ITALIC,Font.SIZE_MEDIUM);

Bitmap Fonts
三个属性
name  //在res文件中,用于程序加载
charset //就是包含的字符,默认为24个字母,数字和一些符号
src //字体文件TrueType所在位置
size    //字体大小
bold //是否加粗,默认为false
trueType //默认为true,根据src属性决定是否生效
antiAliasing //默认为true,如果为false表示别名
logicalName  //逻辑名称,表示不同的字体编码类型,类似css中使用的4个大区字体

//这里注意文档中只介绍了使用ant创建Bitmap font,具体还是要查看API文档

Localization (L10N) 本地化
类似Properties文件的使用,使用键值对的方式保存在Resources中,只支持使用USASCII嘛的形式

读取
Hashtable h = bundle.getL10N("localize", "en"); //bundle应该是Resources的实例

UIManager.setResourceBundle(Hashtable)  //可以用于替换当前语言

Themes 皮肤
使用ResourceEdit.exe 可以很方便的进行编辑

加载到程序:
UIManager.getInstance().setThemeProps(res.getTheme(“myTheme”));

编辑器创建的默认就是Bitmap font

使用字体需要注意版权问题... 使用编辑器的时候,可以通过设置 Anti-aliasing 达到反锯齿的能力

Localization 的使用

Using Transitions and Animations
使用过度效果以及动画

支持的Transition有,可用于form之间进行的转换
Slide
Fade

Slide Transition
在第一个form中定义
CommonTransitions.createSlide(int type, boolean forward, int speed)

参数
type  //定义移动的方向,包括了SLIDE_HORIZONTAL or SLIDE_VERTICAL

forward //用一个boolean值表示,不同方向时,起始位置,比如左到右,不过上到下

speed //用int表示的应该是动画持续的时间,从而在内部计算运行的速度

使用的例子
myForm.setTransitionOutAnimator(CommonTransitions.createSlide(
CommonTransitions.SLIDE_HORIZONTAL, true, 1000));

Fade Transition   渐变效果 (淡入淡出)

CommonTransitions.createFade(int speed) 

参数
speed 同样表示动画持续时间,毫秒为单位

例子
themeForm.setTransitionInAnimator(CommonTransitions.createFade(400));


M3G 用于实现3D功能,需要手机的支持  Jsr184

//加载源码.注意需要使用jdk1.4进行编译

调用的方式通过  M3G.Callback内部类接口的实例来创建3d动画对象

class MyCallback implements M3G.Callback {
   ....
   public void paintM3G(Graphics3D g3d) {
      g3d.clear(background);
      g3d.render(world);
   }
   ...
}

在Components组件上使用的方式为
  private M3G.Callback myCallbackInstance = new MyCallback();
   public void paint(Graphics g) {
M3G.getInstance().renderM3G(g, true, 0, myCallbackInstance);
         // draw some stuff in 2D
         ...
   }

注意这里的区别Graphics3D 和普通的Graphics对象

M3G目前只支持标准的图像文件,而不支持IndexedImage and RGBImage

Logging 日志,可以保存在RMS或者本地文件中

也分为了四种级别
DEBUG  //默认级别
INFO
WARNING
ERROR

记录日志的方式
使用static p(String text) or p(String text,int level) methods.

Log.p(“Finish loading images”)

显示日志
Log.showLog();

创建自定义的组件,只要继承Component对象,然后重写paint方法即可,类似Canvas的操作


public class MyComponent extends Component {
public void paint(Graphics g) {
g.setColor(0xffffff);
g.fillRect(getX(), getY(), getWidth(), getHeight());
g.setColor(0);
g.drawString("Hello World", getX(), getY());
}}
在页面上进行使用的时候,就和其他Components一样 add到容器之上

需要注意的地方
这里使用的颜色都是不带alpha的RGB

使用 getX(), getY() 从容器中获取Components所在的位置,也包括了 getWidth(), getHeight()

控制组件的大小适宜,通过重写calcPreferredSize()方法
protected Dimension calcPreferredSize() {
Font fnt = Font.getDefaultFont();
int width = fnt.stringWidth(“99999-9999”)
    int height = fnt.getHeight();
    return new Dimension(width, height);
}

//这里使用到了获取字体高度和宽度的方法

事件监听

和MIDP原有组件一样,只要重写对应key事件即可
public void keyReleased(int keyCode) {
if(keyCode >= '0' && keyCode <= '9') {
    char c = (char)keyCode;
        inputString += c;
        repaint();
    }
}

Focus 焦点

Components组件中的事件,要求当前组件获取焦点后才会触发
setFocusable(true); //使其获取焦点

使用LookAndFeel绘制
UIManager.getInstance().getLookAndFeel().drawBorder(g, this,getStyle().getFgSelectionColor(), 2);

不是很明白的例子,在Components中
public void paint(Graphics g) {
UIManager.getInstance().getLookAndFeel().setFG(g, this);
Style style = getStyle();
g.drawString(inputString, getX() + style.getPadding(LEFT),
getY() + style.getPadding(TOP));
}

不过一些方法不错 以及常量, 可能第一个方法是初始化组件中参数的状态
229136

Background 使用Painter来绘制,允许透明translucent与不透明opaque

对自定义组件添加Animating动画支持
protected void initComponent() {
    getComponentForm().registerAnimated(this);
}
不能在构造函数中进行注册

自定义组件的例子

关键方法一
  protected Dimension calcPreferredSize() {
      Style style = getStyle();
      Font fnt = style.getFont();
      int width = fnt.stringWidth("99999-9999");
      int height = fnt.getHeight();
      height += style.getPadding(Component.TOP) +
style.getPadding(Component.BOTTOM);
      width += style.getPadding(Component.LEFT) +
style.getPadding(Component.RIGHT);
      return new Dimension(width, height);
  }

用于在窗口变化时候获取合适的显示效果

主要使用到的方法
1:   Style style=getStyle(); //获取当前组件默认样式对象

2:   style.getPadding(LEFT) //获取左内边距

3:   getX(), getY()获取x,y参数

4:   style.getFont().stringWidth(inputString); 获取样式默认字体的宽度,其中inputString为输入的字符串

5:   style.getFont().getHeight() 获取字体的高度

该方法返回的是 new Dimension(width, height); 对象,需要验证下有何效果


注册动画效果
  protected void initComponent() {
      getComponentForm().registerAnimated(this);
  }


修改动画效果细节
public boolean animate() {
     boolean ani = super.animate();
     long currentTime = System.currentTimeMillis();
     if (drawCursor) {
         if ((currentTime - time) > 800) {
             time = currentTime;
             drawCursor = false;
             return true;
         }
     } else {
         if ((currentTime - time) > 200) {
             time = currentTime;
             drawCursor = true;
             return true;
         }
     }
     return ani;
}


影响内存使用的因素

计算一个图片在不同手机上的所占用的内存

长  宽   
16 bit: 128 * 128 * 2 = 32,768   一张全屏的图片所占用的内存
24 bit: 320 * 240 * 4 = 307,200

这里用的是8的倍数来进行计算, 24位会被当做32位计算

可以使用Indexed images 来代替. 不过缺点是只支持256色,优点在于更少的内存使用率

Display's 的init()方法可以关闭一些占用内存较多的特性

Speed 速度方面


Event Dispatch Thread (EDT) 事件发送线程
Display methods callSerially, callSeriallyAndWait, and  invokeAndBlock. 通过这几个方法进行调用特别的线程处


Light Mode 不是很清楚用途
turning off light mode (after Display.init())