`
wanchong998
  • 浏览: 236076 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

使用 LWUIT 的风格、主题和 Painter 特性

阅读更多

Lightweight User Interface Toolkit (LWUIT) 为 Java ME UI 开发人员带来了许多令人印象深刻的功能。Style(风格)、Theme(主题)和 Painter 正是这样三种功能,它们可以方便开发非常吸引人且独立于设备的视觉元素。在本文中,我们将介绍如何使用它们,并探讨一些细微的问题。

我们已经使用 Sprint Wireless Toolkit 3.3.1 开发了演示应用程序。此工具包不仅提供了对 LWUIT 的良好支持,它还提供了许多非常有趣的设备仿真器,比如 HTC Touch 和 Samsung Instinct 的仿真器。如果您希望尝试使用 LWUIT,我强烈建议您在计算机上安装 Sprint WTK。

风格

Style(风格)的概念是 theming(主题)构建的基础。Style 的本质是集中定义每个组件的视觉特征。除了其物理设计(比如其形状),窗口小部件的外观可以根据若干共同属性来定义:

  • Background and foreground colors(背景色和前景色):每个组件有四个颜色属性:两个用于背景,两个用于前景。当组件准备好激活时,该组件被认为处于选中状态。当按钮接受焦点时,例如,它处于选中状态,可以通过单击操作来激活它。一个组件可以使用两种背景颜色来分别表示选中状态和未选中状态。同样,也可以根据两种状态分别定义前景色(通常是用于组件上的文本的颜色)。

  • Text fonts(文本字体):可以使用该平台支持的标准字体样式显示文本,也可以使用 bitmap 字体。每个组件的字体可以通过其风格对象设置。

  • Background transparency(背景透明度):组件背景的透明度可以设置为从完全不透明(默认设置)到完全透明。整数值 0 对应完全透明,而 255 对应完全不透明。

  • Background image(背景图片):默认情况下,组件的背景没有任何图片。但是,该设置可用于指定用作背景的图片。

  • Margin and padding(边距和填充):组件的可视布局(源自 CSS Box 模型)定义边距和填充。图 1 显示了 LWUIT 环境中术语 margin(边距)和 padding(填充)的意思。注意 content area(内容区域)用于显示基本内容,比如文本或图片。Style(风格)允许分别设置四个方向(顶部、底部、左边和右边)的 margin(边距)和 padding(填充)。

    组件布局
    图 1. 组件布局

  • Background painter(背景 painter):特殊用途的 painter 对象可用于自定义一个或一组组件的背景。

Style 类代表在应用程序中使用的每个组件的这些属性的集合,并且拥有相应的存取(accessor)方法。另外,当特定组件的 style 对象被更改时,该类还可以通知已注册的侦听器。

当组件被创建时,一个默认的 Style 对象会与之关联。对于任何重要应用程序,都需要修改视觉属性。一种方法是使用单独的 setter 方法。如果,例如,组件(thiscomponent)的背景色必须更改为红色,则可以使用以下代码:


thiscomponent.getStyle().setFgColor(0xff0000);

第二种修改默认风格设置的方法是创建一种新的风格,然后将其挂接到相关的组件。Style 类拥有允许指定大多数属性的构造函数。以下代码片段设置了一个组件的新风格。


Font font = Font.createSystemFont
(Font.FACE_SYSTEM,Font.STYLE_BOLD,Font.SIZE_LARGE);
byte tr = (byte)255;
Style newstyle = new Style
(0x00ff00, 0x000000, 0xff0000, 0x4b338c, font, tr);
thiscomponent.setStyle(newstyle);

该代码设置了新的前景和背景色、文本的字体以及背景透明度。此处使用的构造函数格式如下:


Style(int fgColor, int bgColor, int fgSelectionColor,
int bgSelectionColor, Font f, byte transparency)

该构造函数还有另外一种形式,除了上述属性之外,它还允许设置图片。该构造函数不支持的属性将需要通过各自的 setter 方法来设置。

最后,通过使用 主题,还可以设置组件中所有类(比如,应用程序中的所有标签)的视觉属性,详见下文。

使用风格

现在,我们应该实现了一个简单的显示效果。接下来,我们介绍如何使用风格来指定组件的外观。我们的应用程序将提供一个组合框,如图 2 所示:

一个简单的组合框

图 2. 一个简单的组合框

此处显示的该组合框的所有属性都是默认值。唯一的例外是前景选择颜色,必须更改该颜色,以提高选中项的可见性。同样,包含该组合框的窗体只修改了一个属性——它的前景色。以下代码显示了如何创建该窗体:


.
.
.
//create a form and set its title
Form f = new Form("Simple ComboBox");

//set layout manager for the form
//f.setLayout(new FlowLayout());

//set form background colour
f.getStyle().setBgColor(0xd5fff9);
.
.
.

代码的头两行是不言自明的,AWT/Swing 开发人员应该非常熟悉。第三行设置窗体的背景色属性。

该组合框也使用类似的方式来实现:


// Create a set of items
String[] items = { "Red", "Blue", "Green", "Yellow" };

//create a combobox with String[] items
ComboBox combobox = new ComboBox(items);

ComboBoxList 的子类,需要使用支持的数据结构。这里我们使用一个字符串数组来代表该数据结构。

准备好组合框后,我们要更改其前景选择颜色,以提高可读性。所以像对窗体所做的一样,我们写了如下一行代码:


combobox.getStyle().setFgSelectionColor(0x0000ff);

但是,当我们编译代码并运行的时候,结果非常让人吃惊——前景色保持不变!它对窗体行得通,那为什么对组合框行不通呢?为了解释这个问题,我们需要记住 LWUIT 的基本结构。像 Swing 一样,LWUIT 是围绕 MVC 概念设计的。所以呈现组件的实体和组件本身逻辑上是分离的。同样,组合框的呈现对象需要是 Component 的子类,这表示它将拥有其自己的风格。每个组合框创建时都有其默认的呈现器,它是 DefaultListCellRenderer 的一个实例。当绘制组合框时,使用的风格属于该呈现器,这就是在组合框的 style 对象中设置前景选择颜色行不通的原因。为了使该设置生效,我们必须修改呈现器的 Style 对象:


//set foreground selection colour for
//the default combobox renderer
//this will work
DefaultListCellRenderer dlcr =
(DefaultListCellRenderer)combobox.getRenderer();
dlcr.getStyle().setFgSelectionColor(0x0000ff);

这一次,当编译该代码时,就可以正常工作了。

主题

在以上部分,我们看到了如何为组件设置单个视觉属性。在有大量 UI 组件的应用程序中,为每个组件设置属性将会是一项庞大的任务,而且容易出错。Theme(主题)允许我们(在一个地方)设置组件的所有类的属性。这不仅简化了为某个特殊类型的所有组件设置属性的任务,而且可以确保任何新添加的组件和应用程序中所有其他同类组件看起来一样。因此 Theme 跨越应用程序的所有屏幕建立了一致的视觉效果。

Theme 是由 key-value 对(其属性为 key,其值为相应的值)组成的列表。列表中的任何项都类似以下格式:


Form.bgColor= 555555

该项指定应用程序中所有窗体的背景色为 RGB 格式的 (hex) 555555。每个主题都被打包为一个 resource(资源)文件,它也可以承载其他项,像用于字体的图片和位图。LWUIT 下载束包含一个 resource editor(资源编辑器),它提供了一种简单的方法来创建主题,并将其打包为一个资源文件。该编辑器可以在该束的 util 目录中找到。双击图标启动它,该编辑器将会如下所示打开。Resource Editor 也集成到了 Sprint WTK 3.3.1 中,可以通过选择 File -> Utilities -> LWUIT Resource Editor 来访问,如图 3 所示。

Resource Editor

图 3. Resource Editor

要创建一个主题,双击左窗格上的 + 按钮,则会打开一个用于输入主题名称的对话框。如图 4 所示。

创建新主题

图 4. 创建新主题

当您单击 OK 时,新主题的名称会显示在左窗格中。单击此主题标签,在有窗格中会出现一个空白主题,如图 5 所示。

空白主题

图 5. 空白主题

要填充该空白主题,单击 Add 按钮,则会打开 Add 对话框。您可以在此对话框顶部的组合框中选择一个组件和属性。在图 6 中,选中的组件是一个窗体,选中的属性是背景色。该颜色的 RGB 值可以作为十六进制字符串输入提供的空白处。您也可以单击该空白旁边的颜色盒来输入颜色值。这会打开一个 color chooser(颜色选择器),选中颜色的值可以直接从中输入对话框中。

将项添加到主题

图 6. 将项添加到主题

单击 OK 按钮,该项会出现在主编辑器窗口的右窗格。注意:可以通过使用相应的按钮编辑或删除项。所有项都完成后,您可以通过选择 File -> Save As 将其保存。如果您使用的是 Sprint WTK,那么应用程序的资源文件必须位于其 res 文件夹。

既然我们已经知道了如何创建主题,下面我们来看一个展示其使用的演示。本部分的演示也有组合框,但是比我们刚才看到的将更加精美。图 7 展示了此演示屏幕。注意:现在该窗体有一个背景图片,并且组合框是围绕复选框构建的。同样,标题栏(在窗体顶部)和菜单栏(在底部)也有与默认颜色(白色)不同的背景颜色。

具有两个组合框的演示屏幕

图 7. 具有两个组合框的演示屏幕

在查看引起外观差异的主题前,让我们快速检查一下用于制作该屏幕的代码。


//initialise the LWUIT Display
//and register this MIDlet
Display.init(this);

try
{
//open the resource file
//get and set the theme
Resources r = Resources.open("/SDTheme1.res");
UIManager.getInstance().
setThemeProps(r.getTheme("SDTheme1"));
}
catch (java.io.IOException e)
{
//if there is a problem print a message on console
//in this case default settings will be used
System.out.println
("Unable to get Theme " + e.getMessage());
}

//create a form and set its title
Form f = new Form("ComboBox Example");

//set layout manager for the form
f.setLayout(new FlowLayout());

//create two sets of items
String[] items = { "Red", "Blue", "Green", "Yellow" };
String[] items2 =
{"Sky", "Field", "Ocean", "Hill", "Meadow"};

//create two comboboxes with these items
ComboBox comboBox = new ComboBox(items);
ComboBox comboBox2 = new ComboBox(items2);

//create new instances of CbPainter
//and set them to combo boxes
//so that a checkbox will be
//the basic building block
CbPainter cbp = new CbPainter();
comboBox.setListCellRenderer(cbp);

CbPainter cbp2 = new CbPainter();
comboBox2.setListCellRenderer(cbp2);


//add the two combo boxes to the form
f.addComponent(comboBox);
f.addComponent(comboBox2);

//create an "Exit" command and add it to the form
f.addCommand(new Command("Exit"));

//set this form as the listener for the command
f.setCommandListener(this);

//show this form
f.show();
<!-- co: the passive voice in the last sentence makes things confusing. if all components should have this method called, then who calls it? does UIManager.setThemeProps() call it on all existing components, or do I have to keep references to all my components and call refreshTheme() on each one or what? ca --><!-- co: I agree this is badly expressed. I have changed the text. bs -->

最开始的时候,我们看到如何从资源文件中提取主题。然后为 UIManager 实例设置该主题。这里我们已经安装了开始的主题。但是当匆忙设置该主题后,屏幕上窗体的一些组件可能会看不见,而且在这些组件上设置主题的效果无法预测。为了确保即使看不见的组件也适当地更新了它们的风格,您应该调用 refreshTheme 方法:


Display.getInstance().getCurrent().refreshTheme();

窗体和组合框是和 前一部分 中的例子一样创建的。没有代码向此演示添加视觉效果,因为所有属性都是在主题中指定的。这里不同的是,我们设置了我们自己的呈现器,而不是通过默认的呈现器来绘制组合框。这在代码中用突出的部分来显示。这些自定义呈现器使组合框看起来不一样。

呈现器本身非常简单。它所要做的是就是实现接口 ListCellRenderer 中指定的方法。由于我们想要我们的组合框封装复选框,该呈现器扩展了 CheckBoxDefaultLookAndFeel 类的 drawComboBox 方法使用该呈现器获得用于绘制组合框的组件。在这种情况下,这样获得的组件是一个复选框,如以下代码所示。


//objects of this class will be used to paint the combo boxes
class CbPainter extends CheckBox implements ListCellRenderer
{
public CbPainter()
{
super("");
}

//returns a properly initialised component
//that is ready to draw the checkbox
public Component getListCellRendererComponent
(List list,Object value,int index,boolean isSelected)
{
setText("" + value);
if (isSelected)
{
setFocus(true);
setSelected(true);
}
else
{
setFocus(false);
setSelected(false);
}

return this;
}

//returns the component required for drawing
//the focussed item
public Component getListFocusComponent(List list)
{
setText("");
setFocus(true);
setSelected(true);

return this;
}
}

组合框可以具有多种样式,而不仅仅是纯列表或复选框。他可以围绕一些其他的标准组件,或者甚至是有自己独特外观的新组件来构建。图 8 展示了一个拥有单选按钮呈现器的组合框

具有单选按钮呈现器的组合框

图 8. 具有单选按钮呈现器的组合框

<!-- co: what app is figure 9 taken from? the sprint developer tools? ca --><!-- co: This the theme as seen on Resource Editor. I have expalined here. bs -->

要查看定义我们的演示的外观的主题,您将需要在计算机上安装 Resource Editor。启动 LWUIT 附带 或者集成到 Sprint Toolkit 中的 Resource Editor。打开 Resource Editor 后,选择 File -> Open 找到并打开资源文件。Resource Editor 将在左窗格的 Themes 下面显示 SDTheme1。单击 SDTheme1 将在右窗格中显示该主题的详细信息,如图 9 所示。

该演示的主题

图 9. 该演示的主题

首先要注意的一点是,在顶部有一个项是以白色文字显示的。所有这样的项都是默认的。在我们的例子中,唯一特定于组件的字体设定是用于软件按钮的——左下角的 Exit 按钮。窗体标题和组合框字符串的字体没有定义。这些字体将根据默认设置呈现。

在我们较早的例子中,我们看到文本的选择颜色必须在呈现器中设置。在当前的例子中,我们知道呈现实际上是由复选框呈现器完成的。所以已经为复选框定义了背景和前景色,实际上,呈现文本的颜色和文本背景(都有接受焦点和不接受焦点两种状态)是根据这些定义。如图 10 所示。

前景和背景颜色

图 10. 前景和背景颜色

在上图中,我们可以看到复选框透明度值 127 的效果(半透明)。由于该设置,下拉列表中的三个未选中的项呈中灰色。您可以更改该值,看看这些背景如何改变。顺便说以下,当您更改主题时,没必要重新构建应用程序。只需保存资源文件并单击 Run。

新主题安装好后,除了通过使用 Style 类的某个 accessor 方法手动更改的那些属性(之前 讨论过的)外,所有的可用的风格都会更新。但是,如果您想要新的主题对那些甚至手动更改的属性有效,那么使用 Style 中的某个 setter,它有两个参数,第二个是一个布尔变量。例如:


setFgColor(int fgColor, boolean override);

如果当属性被手动更改时,该布尔参数被设置为 true,那么在新主题中指定的值也将覆盖手动设置的值。代码如下所示:


thiscomponent.getStyle().setFgColor(0xff0000, true);

Painter

Painter 界面允许组件的背景按您所想的显示。回忆一下我们关于风格的讨论,我们看到其中一个属性是 background painter(背景 painter)。在这部分,我们将看到如何使用一个简单的背景 painter。

参考我们的演示截屏,绘制文本的背景颜色无法通过风格或主题更改。当我们分析组合框(如图 11 所示)的结构以及呈现它的顺序时,原因变得很清楚。

组合框的结构

图 11. 组合框的结构

当组合框需要重新绘制时(比如,由于它刚接受了焦点),以下事件就会按顺序进行。

  1. 删除旧的组合框。方法是绘制一个同样大小的填满的矩形,其透明度为 0(完全透明)。
  2. 然后绘制复选框选择和文本。
  3. 接着绘制组合框按钮。
  4. 最后,绘制组合框边框。

现在我们看到第一步之后,没有重新绘制组合框背景。所以这部分仍为完全透明的层,显示窗体的背景。您可以在主题中更改窗体的背景色,并且您将看到此颜色也将变为组合框的背景颜色。

如果我们现在想要组合框背景有一个不同的颜色(或者图案、图片),我们需要使用 Painter。我们应该看到一个简单的 painter 的样子,以及如何使用它。

<!-- 65-char code ruler - make sure your code is narrower than this 12345678901234567890123456789012345678901234567890123456789012345 -->

public class ComboBgPainter implements Painter
{
private int bgcolor;

public ComboBgPainter(int bgcolor)
{
this.bgcolor = bgcolor;
}

public void paint(Graphics g, Rectangle rect)
{
//probably redundant
//but save the current colour anyway
int color = g.getColor();

//set the given colour
g.setColor(bgcolor);

//get the position and dimension
//of rectangle to be drawn
int x = rect.getX();
int y = rect.getY();
int wd = rect.getSize().getWidth();
int ht = rect.getSize().getHeight();

//draw the filled rectangle
g.fillRect(x, y, wd, ht);

//restore colour setting
g.setColor(color);
}
}

该代码非常简单——它所做的是,使用传递给构造函数的颜色绘制一个填充的矩形。该矩形在 rect 定义和位置和方向绘制。

我们现在要做的是,将该 painter 钩挂到需要描绘其背景的组合框。我们通过在实例化两个组合框的代码后添加突出显示的行来完成。注意:将只描绘一个组合框的背景。


//create two comboboxes with these items
ComboBox combobox = new ComboBox(items);
ComboBox combobox2 = new ComboBox(items2);

//set the painter
combobox.getStyle().setBgPainter
(new ComboBgPainter(0x4b338c));

图 12 显示左侧的组合框的背景已经按预期进行了绘制。如果还希望描绘另一个组合框的背景,我们将使用同一个 painter。实际上,我们可以创建 painter 的实例,然后在所有组合框中设置同一实例。

描绘有背景的组合框

图 12. 绘有背景的组合框

结束语

我们已经了解了如何借助 LWUIT 平台,使用 StyleThemePainter 来创建一组有视觉吸引力的统一化组件。最近 LWUIT 已经开放了源代码。详细研究这些源代码将会是一种令人陶醉的体验,而且可以帮助您合理地利用该库并实现丰富的用户体验。

分享到:
评论

相关推荐

    最新LWUIT_1_5

    LWUIT 1.5的发布意味着它可能解决了旧版本中的一些已知问题,并添加了对当时最新手机特性和技术的支持。 LWUIT的核心特性包括: 1. **组件库**:LWUIT提供了丰富的组件集合,如按钮、文本框、标签、列表、表格等,...

    Lwuit入门程序测试一下Demo

    4. **设置主题**:通过ThemeResourcer类和皮肤文件,你可以为应用设定一套独特的视觉风格。 5. **添加事件监听器**:为了响应用户的操作,如点击按钮,需要为组件添加事件监听器。 6. **运行和测试**:最后,调用...

    lwuit实例 lwuit j2me 界面

    2. **样式表和主题**:LWUIT允许开发者通过XML样式表定义组件的颜色、字体、边框等视觉属性,可以创建和应用全局主题,使应用保持一致的视觉风格。 3. **事件处理**:LWUIT支持事件监听,可以通过添加事件处理器来...

    lwuit1.4介绍

    LWUIT 1.4 是一个轻量级用户界面工具包(Lightweight User Interface Toolkit),专为Java ME(J2ME)平台设计,用于构建功能丰富的移动应用程序。这个版本的LWUIT引入了一个名为HTMLComponent的新组件,极大地扩展...

    lwuit_demo_src.rar_DEMO_J2ME lwuit de_LWUIT_lwuit demo

    这个"lwuit_demo_src.rar_DEMO_J2ME lwuit de_LWUIT_lwuit demo"压缩包包含的是LWUIT库的示例源代码,对于学习和理解LWUIT的使用方法非常有帮助。 LWUIT的主要目标是提供一套轻量级的UI组件,使得开发者能够在资源...

    LWUIT 开发指南第七章里的 Hello Painter 源代码

    本源码是博客《解读 LWUIT 之十:画笔(Painters)》中作者写的 Hello Painter 源代码。博客链接地址:http://blog.csdn.net/defonds/archive/2010/03/03/5341204.aspx。

    LWUIT1.3code.rar_LWUIT

    通过对LWUIT 1.3源代码的学习,开发者不仅能掌握LWUIT库的使用,还能深入了解UI设计的原理和实践,提升J2ME应用开发能力。同时,由于LWUIT后来被集成到NetBeans IDE的MIDP插件中,学习LWUIT对于使用NetBeans进行J2ME...

    LWUIT1.2-src

    1. **新组件和特性**:可能增加了新的UI组件,比如新的布局管理器、控件或者动画效果,以提高用户体验并增强应用程序的视觉表现力。 2. **资源封装和主题编辑**:LWUIT 1.2可能提升了资源管理和主题编辑工具的功能...

    lwuit 开发文档

    开发者需要了解如何利用LWUIT提供的各种皮肤(skin)和样式(style)来美化界面,以及如何使用主题商店中的主题来更新应用程序的视觉效果。此外,文档中可能还会包含异常处理、资源管理和应用打包等高级话题,这些都...

    lwuit.rar_J2ME ui_LWUIT_j2me

    对于开发者来说,这份CHM文档是学习和使用LWUIT的重要资源,它会指导如何初始化LWUIT环境,创建和布局组件,处理用户事件,以及如何利用主题和动画功能。 总的来说,LWUIT是J2ME开发中不可或缺的工具,它极大地提高...

    lwuit1.4 jar包

    2. **主题和皮肤**:LWUIT支持主题和皮肤的定制,允许开发者通过XML配置文件改变应用的整体外观,从而实现跨设备的一致用户体验。 3. **资源管理**:LWUIT有内置的资源管理机制,可以方便地处理图像、音频和视频等...

    LWUIT j2me UI例子

    这个程序可能会展示一系列使用LWUIT构建的UI组件、布局和主题,让开发者直观地了解LWUIT的功能和用法。可能包括按钮、文本框、列表、表视图、对话框等各种控件的示例,以及不同布局方式的展示。此外,它可能还包括一...

    使用Lwuit中遇到的问题解决

    LWUIT( Lightweight UI Toolkit)是Java ME平台上用于构建用户界面的一个库,它提供了一组丰富的组件和动画效果,使得开发者能够创建具有吸引力的移动应用。在使用LWUIT时,可能会遇到各种问题,以下是一些常见的...

    Lwuit精简解说下载

    此外,它可能还讲解了如何使用LWUIT的皮肤机制来改变应用的主题,使应用能够在不同设备上保持一致的视觉风格。 “Lwuit的21条 - Face Code, Brain bloom - 博客园.files”这部分可能是来自博客园网站的一篇文章,...

    LWUIT.jar LWUIT.jar

    LWUIT.jarLWUIT.jarLWUIT.jarLWUIT.jarLWUIT.jarLWUIT.jar

    lwuit.rar_LWUIT_java 项目_手机动态

    - **主题和样式**:LWUIT 允许开发者定义全局主题,可以快速改变整个应用的外观和感觉,而无需修改每个组件的代码。 - **跨平台兼容**:由于基于Java,LWUIT 应用程序可以在支持Java ME的多个手机平台上运行,具有...

    LWUIT1.3 完整jar包及api文档

    2. **主题和样式**:LWUIT支持自定义主题,允许开发者通过XML配置文件定义UI元素的颜色、字体、边框等样式,从而实现应用程序的统一视觉风格。 3. **动画支持**:LWUIT内置了动画机制,可以轻松创建平滑的过渡效果...

    LWUIT1.4 最新源代码

    压缩包中的"LWUIT"文件很可能是包含了LWUIT 1.4版本的源代码,开发者可以通过查看源代码来了解其内部工作原理,学习如何使用和扩展LWUIT,或者为框架贡献新的功能和改进。 总的来说,LWUIT 1.4是一个强大的工具,...

    lwuit.rar_J2ME lwuit_LWUIT_j2me_j2me LWU_九宫

    5. **主题和样式**:LWUIT允许开发者定义自己的主题和样式,通过修改CSS文件可以改变九宫图的颜色、字体、边框等视觉效果。 6. **资源管理**:如果九宫图包含图片或其他资源,LWUIT提供了资源管理器来加载和缓存...

    LWUIT_3_1英文原版.part1

     Sun在2008年的JavaOne会议上向开发者社区推荐了LWUIT,展示了预先发布的二进制文件库,附加工具和扩展文档,让开发者可以快速上手,现在Sun把整个源代码都开放出来,更方便开发者利用LUWIT开发JavaME应用。

Global site tag (gtag.js) - Google Analytics