内容


OpenLaszlo —— 一个快速构建和部署富 Internet 应用程序的平台

理解 OpenLaszlo 是什么,以及它如何简化富 Internet 应用程序的开发和部署

Comments

概述

EIA 开发人员面临的最大挑战之一是浏览器的兼容性。由于 OpenLaszlo 基于“一次编写,到处运行”的 Java™ 语言范式,因此可确保基于 OpenLaszlo 的应用程序可以跨多种操作系统在不同的浏览器中运行。

架构

下面的图显示 OpenLaszlo 的服务器端和客户端架构。

图 1. OpenLaszlo 服务器和客户端子系统
OpenLaszlo 服务器和客户端子系统架构图
OpenLaszlo 服务器和客户端子系统架构图

OpenLaszlo 服务器

OpenLaszlo 服务器是一个 Java servlet/JSP 应用程序。该服务器使 LZX 应用程序的开发轻而易举。

OpenLaszlo 服务器由 5 个子系统组成:

  • Interface Compiler— Interface Compiler 由一个 LZX Tag Compiler 和一个 Script Compiler 组成,它将源文件转换成可执行(SWF)文件,并将它们以字节码的形式提供给客户端浏览器中运行的插件(例如 Flash 或 J2ME),或者以 JavaScript(DHTML)的形式提供给浏览器,由浏览器本身执行。
  • Media Transcoder— Media Transcoder 将所有媒体资产转换成一种统一格式,以便由 OpenLaszlo 的目标客户端呈现引擎来呈现。这使得 OpenLaszlo 应用程序可以在同一个画布上以统一的方式提供各种受支持的媒体类型,而不必使用多个助手应用程序或附加的重放软件。Media Transcoder 可自动呈现以下媒体类型: JPEG、GIF、PNG、MP3、TrueType 和 SWF(仅指艺术/动画)。
  • Data Manager— Data Manager 充当 OpenLaszlo 应用程序与网络上其他应用程序,例如数据库和 XML Web 服务之间的接口。它由一个数据编译器和一系列的数据连接器组成,数据编译器将数据转换成一种压缩的二进制格式,而数据连接器则使 OpenLaszlo 应用程序可以通过 XML/HTTP 检索数据。
  • Cache— Cache 包含任何应用程序的最近编译版本。当 OpenLaszlo 应用程序第一次被请求时,它将被编译,产生的 SWF 文件被发送到客户端。与此同时,一个副本缓存在服务器上,所以随后的请求就不必等待编译。

OpenLaszlo 客户端

OpenLaszlo 的客户端架构主要由一些 Laszlo 基础类组成,它为运行 OpenLaszlo 应用程序提供运行时环境。每当有客户端通过 URL 调用 OpenLaszlo 应用程序时,所需的运行时库也随之一起下载。 客户端总是维护与服务器的连接。

OpenLaszlo 客户端主要由以下子系统组成:

  • Event System— Event System 负责处理各种基于用户的事件,例如鼠标点击或数据提交。 它还通过在客户端上执行各种不同的操作来提高应用程序的性能, 例如进行排序和验证,而不是直接将那些数据传递给服务器。
  • Data Loader/Binder—Data Loader 接收从服务器端发来的数据,并将那些数据绑定到相应的 UI 组件,例如客户端上的菜单、 文本框和文本域。
  • Layout and Animation System—Layout and Animation System 处理各种与动画相关的算法,使用户可以以视觉上连续的方式查看组件。它还通过极少的编程,使用相对和绝对像素定位来处理各种组件的位置。

请求周期

一个典型的请求遵循以下路径:

  1. 用户通过浏览器以 URL 的形式发送对资源的请求。
  2. OpenLaszlo 服务器根据 URL 获取资源,并将它发送到 Interface Compiler,以便进行编译。
  3. Interface Compiler 将 LZX 应用程序描述标记和 JavaScript 转换为可执行(SWF) 字节码,以便传送到 OpenLaszlo 客户端环境。 该代码被放在缓存中,并从缓存中发送到客户端。
  4. 取决于调用应用程序的方式,上述代码以 SWF 文件或嵌有 SWF 对象的 HTML 文件的形式, 随适当的 Laszlo 基础类一起传送。
  5. 如果影响返回的格式为 HTML,则由浏览器显示应用程序。如果返回的格式为 SWF, 则由 Flash 播放器播放应用程序。
  6. 用户在客户端输入请求数据,并提交该数据。
  7. OpenLaszlo 服务器调用适当的数据连接器,后者取 XML 数据。
  8. OpenLaszlo 服务器将数据发送回客户端。
  9. 客户端上的 Laszlo 基础类将数据绑定到适当的 UI 对象。系统以响应数据更新屏幕组件。

图 2 显示上述一个典型的 OpenLaszlo 应用程序请求周期。

图 2. 请求周期
上述请求周期的流程图
上述请求周期的流程图

第一个 OpenLaszlo 应用程序

开发 OpenLaszlo 应用程序需要完成以下步骤:

  • 使用文本编辑器编写 OpenLaszlo 程序(使用 XML 和 JavaScript)。
  • 将该文件保存为 LZX 文件。
  • 将 LZX 文件编译为 SWF 文件或 DHTML,可以手动编译,也可以使用 OpenLaszlo 服务器,并在浏览器中查看输出。

编写 OpenLaszlo 应用程序

如前所述,OpenLaszlo 应用程序是一个 XML 文档。因此,可以使用文本编辑器编写代码。 清单 1 中的代码是一个简单的 HelloWorld LZX 应用程序。

清单 1. HelloWorld.lzx
<canvas height="350" width="1050" bgcolor="#FFBE7D" >
	<view width="500" height="250" align="center" valign="middle" bgcolor="#FFFF66">
		<text align="center" valign="middle">
			<font size="25">Welcome to Hello World!</font>
		</text>
	</view>
</canvas>

保存源文件

下载,将该脚本保存为 HelloWorld.lzx。该文件必须保存在 Server/lps-4.0.x 目录中的某个地方,该目录在 OpenLaszlo Server 的安装目录下。

编译和运行脚本

编译 LZX 文件的最容易的方式是使用 OpenLaszlo 服务器。确保计算机上正在运行 Apache Tomcat,让浏览器访问以下 URL: http://localhost:8080/lps-4.0.x/path。在此,path 是 LZX 文件相对于 Server/lps-4.0.x 目录的路径。

例如,如果脚本被保存为 Server/lp2-4.0.x/hello/HelloWorld.lzx,那么编译该 OpenLaszlo 应用程序的 URL 为 http://localhost:8080/lps-4.0.x/hello/HelloWorld.lzx,如图 3 所示。 servlet 容器将把 HTTP 请求传递给 OpenLaszlo 服务器。服务器打开和编译适当的 LZX 文件, 生成输出,并将它保存在一个临时目录中。

然后, OpenLaszlo 服务器将生成的输出发送到浏览器。如果应用程序被编译为 Flash,那么生成的 SWF 文件和相关文件被缓存起来。 如果 LZX 文件未被修改,那么随后对它的请求将快得多, 因为不需要重新编译。如果编译失败, 浏览器上将显示一条错误消息。

图 3. 示例 hello world OpenLaszlo 应用程序
示例 Hello World OpenLaszlo 应用程序截图
示例 Hello World OpenLaszlo 应用程序截图

显示屏底部显示的是一个开发工具,其中包含一些按钮,这些按钮可用于查看 OpenLaszlo 源代码、部署应用程序、 编译源代码和执行其他功能。可以通过传递适当的请求类型和运行时目标作为参数, 避开该开发工具。例如:

http://127.0.0.1:8080/lps-4.3.0/helloWorld/HelloWorld.lzx?lzr=swf9&lzt=html

以及:

http://127.0.0.1:8080/lps-4.3.0/helloWorld/HelloWorld.lzx?lzr=dhtml&lzt=html

图 4 显示 helloWorld 应用程序通过参数避开工具条的一个例子。

图 4. 示例 Hello World OpenLaszlo 应用程序
示例 Hello World OpenLaszlo 应用程序,其中没有开发工具条
示例 Hello World OpenLaszlo 应用程序,其中没有开发工具条

基本组件

OpenLaszlo 附带了一组表示简单组件和富组件的类,以使 LZX 编程变得更容易和更快捷。 BaseComponent 类是 LzView 的子类,同时又是所有 LZX 组件的超类。

画布

canvas 标记表示 LZX 应用程序中所有视图和组件的最顶层容器。 每个 LZX 应用程序只有一个画布。当 LZX 编译器遇到 canvas 标记时,将实例化 LzCanvas 类。例如,清单 2 中的代码显示如何使用 canvas 标记和它的一些属性。

清单 2. Canvas.lzx
<canvas width="450" bgcolor="#6699FF" height="200" title="Canvas">
	<text align="center" valign="middle">
			<font size="25">Openlaszlo World!</font>
	</text>
</canvas>

可以使用 http://localhost:8080/lps-4.0.x/canvas/Canvas.lzx 调用上述应用程序。图 5 显示生成的输出。

图 5. 画布
显示文本 'OpenLaszlo World!' 的画布
显示文本 'OpenLaszlo World!' 的画布

视图

一个视图表示一块矩形区域,其中可显示文本和其他组件。 可以使用 view 标记或通过实例化 LzView 类创建视图。例如, 清单 3 显示一个使用 view 标记的 LZX 应用程序。

清单 3. View.lzx
<canvas width="300" bgcolor="#ddddee" height="200">
	<view align="center" valign="middle" bgcolor="#6699FF" width="300" height="150"/>
</canvas>

可以通过 http://localhost:8080/lps-4.0.x/view/View.lzx 查看上述应用程序。图 6 显示 view.lzx 文件生成的输出。

图 6. 使用视图
一个空的蓝色矩形,表示视图
一个空的蓝色矩形,表示视图

在典型的 LZX 应用程序中,常常会使用多个视图,视图之间相互嵌套。 清单 4 显示一个包含嵌套视图的 LZX 应用程序。

清单 4. NestedView.lzx
<canvas height="370">
	<view width="150" height="150" bgcolor="black">
		<view width="100" height="100" bgcolor="white">
			<view width="50" height="50" bgcolor="gray"/>
		</view>
	</view>
</canvas>

可以通过浏览 http://localhost:8080/lps-4.0.x/view/NestedView.lzx 调用上述应用程序。图 7 显示生成的输出。

图 7. 使用嵌套视图
表示一个视图的灰色矩形,它包含在一个蓝色矩形中,后者表示父视图
表示一个视图的灰色矩形,它包含在一个蓝色矩形中,后者表示父视图

还可以使用 view 标记显示或播放外部资源,例如图像、MP3 文件和其他 Flash 文件。 受支持的媒体类型有 JPG、GIF、PNG、MP3 和 SWF。注意,对 MP3 的支持仅限于以 44.1 KHz、22 KHz, 11 KHz, 8 KHz 和 5.5 KHz 频率采样的音频文件。清单 5 显示一个例子 LZX 应用程序,该 LZX 应用程序使用 view 显示一个图像。

清单 5. ResourceView.lzx
<canvas width="300" bgcolor="#ddddee" height="200">
	<view align="center" resource="IBMLogo.jpg" valign="middle" bgcolor="#6699FF" 
		width="300" height="150"/>
</canvas>

可以使用 http://localhost:8080/lps-4.0.x/view/ResourceView.lzx 调用上述应用程序。图 8 显示生成的输出。

图 8. 使用资源视图
一个资源视图,其中显示一个蓝色矩形,左上角是一个 IBM logo
一个资源视图,其中显示一个蓝色矩形,左上角是一个 IBM logo

窗口

Window 对象表示一个可调窗口。Window 类是 WindowPanel 的子类,后者是 BaseWindow 的子类。BaseWindow 又是 BaseComponent 的直接子类。清单 6 中的 Window.lzx 文件是一个 LZX 应用程序,它显示一个可调窗口。

清单 6. Window.lzx
<canvas width="450" bgcolor="#6699FF" height="200" title="Canvas">
	<window align="center" valign="middle" resizable="true" width="300" height="150">
		<text>OpenLaszlo World!</text>
	</window>
</canvas>

可以使用 http://localhost:8080/lps-4.0.x/window/Window.lzx 调用上述应用程序。 图 9 显示生成的输出。

图 9. 窗口
蓝色画布中有一个浮动窗口,其中包含文本'OpenLaszlo World!'
蓝色画布中有一个浮动窗口,其中包含文本'OpenLaszlo World!'

警告

Alert 对象表示一个显示消息的模态对话框。Alert 对话框带有一个 OK 按钮。默认情况下 Alert 对话框不会显示。 必须调用 Alert 的 open 方法才能使之可见。 Alert 类是 ModalDialog 类的子类,后者又是 WindowPanel 的子类。Modal Dialog 对象表示 一个可移动的浮动视图。清单 7 中的代码显示如何使用 Alert 对话框。

清单 7. Alert.lzx
<canvas>
	<alert name="warning">Press OK to continue.</alert>
	<script>
		canvas.warning.open ();
	</script>
</canvas>

可以使用 http://localhost:8080/lps-4.0.x/alert/Alert.lzx 调用上述应用程序。图 10 显示生成的输出。

图 10. Alert 对话框
Alert 对话框
Alert 对话框
清单 8. AlertWithButtons.lzx
<canvas>
	<alert name="warning" buttonl="OK" button2="No">
		Click OK to Process.
		<handler name="onresult">
		if (this.result) {
			parent.message.setText("Processing Started");
		} else {
		parent.message.setText ("Processing Stopped'");
		}
		</handler>
	</alert>
	<script>
		canvas.warning.open ();
	</script>
	<text name="message"> Do you want to start processing?</text>
</canvas>

AlertWithButtons 以包含 Yes/No 按钮的 Alert 框的形式请求用户确认,并采取适当的行动。

按钮

Button 对象表示一个可点击按钮,它会引发一个事件,所以可以在点击时执行某个动作。该类是 BaseButton 的子类,后者又是 BaseComponent 的子类。清单 9 中的 Button.lzx 文件是一个使用按钮的 LZX 应用程序。按钮的文本是 “Hello World!!”。

清单 9. Button.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
	<button width="200" height="80" align="center" valign="middle">
		Hello World!!</button>
</canvas>

通过浏览 http://localhost:8080/lps-4.0.x/layout/Button.lzx 运行该例子。图 11 显示生成的输出。

图 11. 包含按钮的画布
蓝色矩形中包含一个可点击按钮,按钮中央标有文本'Hello World!!'
蓝色矩形中包含一个可点击按钮,按钮中央标有文本'Hello World!!'

使用布局

通过布局管理器可以布置容器中的组件。 LzLayout 类是 LzNode 的子类,负责布置视图。 LzLayout 类是提供该功能的基类。 永远不要直接实例化这个类,而是创建它的子类的一个实例。下面是 LzLayout 的一些子类。

SimpleLayout

SimpleLayout 用于水平或垂直地接连放置组件。 可以使用 simplelayout 标记创建它的实例,如下所示。

清单 10. SimpleLayout.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
	<simplelayout axis="x" spacing="4"/>
	<view align="center" valign="middle" bgcolor="silver" width="100" height="100"/>
	<view align="center" valign="middle" bgcolor="gray" width="100" height="100"/>
	<view align="center" valign="middle" bgcolor="blue" width="100" height="100"/>
</canvas>

使用 http://localhost:8080/lps-4.0.x/layout/SimpleLayout.lzx 调用该示例。图 12 显示生成的输出。

图 12. 简单布局
蓝色画布上并排放置了三个不同颜色的正方形
蓝色画布上并排放置了三个不同颜色的正方形

ResizeLayout

ResizeLayout 类似于 SimpleLayout,通过它可以水平或垂直地定位视图。 但是,通过 ResizeLayout 还可以重新调整受管的视图,如清单 11 所示。

清单 11. ResizeLayout.lzx
<width="450" bgcolor="#6699FF" height="200">
	<resizelayout axis="y" spacing="20"/>
	<view valign="middle" width="100" height="100" bgcolor="silver"/>
	<view valign="middle" width="100" height="100" bgcolor="gray"/>
	<view valign="middle" width="100" height="100" bgcolor="blue" 
	options="releasetolayout"/>
</canvas>

可以使用 http://localhost:8080/lps-4.0.x/layout/ResizeLayout.lzx 调用上述应用程序。图 13 显示生成的输出。

图 13. 可调布局
蓝色画布上有 3 个并排的不同有色矩形
蓝色画布上有 3 个并排的不同有色矩形

SimpleBoundsLayout

SimpleBoundsLayoutSimpleLayout 一样水平或垂直地定位视图。但是,SimpleBoundsLayout 确保当一个视图旋转时,不会与其他视图重叠。下面清单 12 显示了一个例子。

清单 12. SimpleBoundsLayout.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
	<simpleboundslayout axis="x"/>
	<view valign="middle" width="100" height="100" bgcolor="silver"/>
	<view valign="middle" width="100" height="100" bgcolor="gray" rotation="30"/>
	<view valign="middle" width="100" height="100" bgcolor="blue"/>
</canvas>

可以使用 http://localhost:8080/lps-4.0.x/layout/SimpleBoundsLayout.lzx 调用该应用程序。 图 14 显示生成的输出。

图 14. SimpleBoundsLayout
蓝色画布上有 3 个有色方块,表示并排的视图
蓝色画布上有 3 个有色方块,表示并排的视图

ReverseLayout

使用 ReverseLayout 时,视图从右到左排列(沿着 x 轴)或者从下到上排列( 沿着 y 轴)。清单 13 显示一个使用 ReverseLayout 的 LZX 应用程序。

清单 13. ReverseLayout.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
	<reverselayout axis="x" end="false" spacing="20"/>
	<view align="center" valign="middle" width="100" bgcolor="silver"/>
	<view align="center" valign="middle" width="100" bgcolor="gray"/>
	<view align="center" valign="middle" width="100" bgcolor="blue"/>
</canvas>

通过 http://localhost:8080/lps-4.0.x/layout/ReverseLayout.lzx 运行该例子。 图 15 显示生成的输出。

图 15. 反转布局
蓝色画布上有 3 个并排的有色矩形,表示 3 个视图
蓝色画布上有 3 个并排的有色矩形,表示 3 个视图

ConstantLayout

这种布局将视图层相互层叠。 和 SimpleLayout 一样,可指定 axis 属性。然后,ContantLayout 根据 xoffsetyoffset 值指定的像素数错开每个视图。 结果是按这些值叠放的视图。

清单 14. ConstantLayout.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
	<constantlayout axis="x" value="10"/>
	<view valign="middle" width="300" height="150" bgcolor="silver"/>
	<view valign="middle" width="200" height="80" bgcolor="gray" xoffset="-15"/>
	<view valign="middle" width="40" height="40" bgcolor="blue" xoffset="-50"/>
</canvas>

可以使用 http://localhost:8080/lps-4.0.x/layout/ConstantLayout.lzx 调用该应用程序。 图 16 显示生成的输出。

图 16. Constant 布局
相互嵌套的不同颜色的矩形和正方形
相互嵌套的不同颜色的矩形和正方形

WrappingLayout

当空间不够时,WrappingLayout 通过换行或换列包装它管理的视图。清单 15 显示一个 例子。

清单 15. WrappingLayout.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
	<wrappinglayout axis="x" spacing="20"/>
	<view align="center" valign="middle" bgcolor="silver" width="200" height="100"/>
	<view align="center" valign="middle" bgcolor="gray" width="200" height="100"/>
	<view align="center" valign="middle" bgcolor="blue" width="200" height="100"/>
</canvas>

使用 http://localhost:8080/lps-4.0.x/layout/WrappingLayout.lzx 调用上述应用程序。 图 17 显示生成的输出。

图 17. Wrapping 布局
有色矩形太大,无法并排排列
有色矩形太大,无法并排排列

事件处理

为了使程序更具交互性, OpenLaszlo 对象可以在用户做出动作后产生事件,例如 buttonclick。然后将事件与 一个事件处理程序关联,后者包含该对象产生事件时将执行的代码。 有几种方式可以将事件与事件处理程序相关联。 一种方式是在对象的标记声明中将事件处理程序的名称赋给事件名称,如清单 16 所示。下面显示的标记创建一个 Window 对象,它的 onx 事件与事件处理程序 myHandler 相关联。

清单 16. window.lzx
<window name="win" onx="myHandler">

另一种方法是编写一个方法,将该方法嵌入在对象的标记声明中, 并将事件处理程序赋给那个方法的 event 属性。 清单 17 中的代码片段在标记中将一个按钮的 onclick 事件与事件处理程序相关联。

清单 17. Window.lzx
<button>
	<handler name="onclick">
		// Event handler code
	</handler>
</button>

清单 18 中的例子显示一个按钮发出的 onclick 事件,该事件被映射到一个事件处理程序。

清单 18. EventWiring.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
	<button width="200" height="80" align="center" valign="middle">Hello Button
	<handler name="onclick">
		setAttribute("text", "Hello Button Clicked");
		setAttribute ('width', 200);
	</handler>
	</button>
</canvas>

可以通过浏览 http://localhost:8080/lps-4.0.x/event/EventWiring.lzx 执行例子 EventWiring.lxz。图 18 显示最初生成的输出,以及单击按钮触发事件后的输出。

图 18. 事件处理
两个屏幕快照,各自的画布中有一个按钮
两个屏幕快照,各自的画布中有一个按钮

或者,还可以将事件处理程序的代码嵌入在对象标记中,如 图 19 所示。

清单 19. EmbeddedEventHandling.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
	<button width="200" height="80" align="center" valign="middle" 
		onclick="setAttribute ('text', 'Hello Button Clicked');
		setAttribute ('width', 200);">
		Hello Button
	</button>
</canvas>

全局事件处理程序

全局事件处理程序可以用 JavaScript 函数编写,这些函数可以从多个对象中调用。 例如,清单 20 中的代码 定义 myHandler 函数, 该函数可以从程序中的任何地方调用。

清单 20. GlobalEventHandler.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
	<button width="200" height="80" align="center" valign="middle" id="button1" 
		onclick="globalHandler()"> Hello Button
	</button>
	<script>
		<![CDATA[
			function globalHandler () {
				button1.setAttribute ("text", "Hello Button Clicked");
				button1.setAttribute ('width', 200);
			}
		]]>
	</script>
</canvas>

可以使用 http://localhost:8080/lps-4.0.x/event/GlobalEventHandler.lzx 编译和调用上述应用程序。

传递对象的引用

在 OpenLaszlo 中,甚至可以将对象引用传递给方法,如清单 21 所示。

清单 21. PassingObjectReference.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
	<simplelayout axis="x"/>
	<button width="200" height="80" align="center" valign="middle" id="button1" 
		onclick="globalHandler (this)"> Hello Button 1
	</button>
	<button width="200" height="80" align="center" valign="middle" id="button2" 
		onclick="globalHandler (this)"> Hello Button 2
	</button>
	<script>
		<![CDATA[
			function globalHandler (b) {
				b.setAttribute ("text", "Hello Button Clicked");
				b.setAttribute ('width', 200);
			}
		]]>
	</script>
</canvas>

可以使用 http://localhost:8080/lps-4.0.x/event/PassingObjectReference.lzx 编译和调用该应用程序。

添加动画

通常,可以通过更改对象的 x 和 y 坐标值实现对象的动画效果。 OpenLaszlo 中的动画很容易通过使用 animatoranimatorGroup 标记来实现。animator 标记在对象中使用,用于执行移动,而 animatorGroup 标记用于组合多个 animator 标记,以实现多种类型的动画。清单 22 中的 LZX 应用程序显示一个按钮,该按钮沿着一条水平线移动。

清单 22. SimpleAnimation.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
	<button width="200" height="80" align="center" valign="middle" 
		text="Animated Stuff">
		<animator attribute="x" from ="0" to="300" duration="5000"/>
	</button>
</canvas>

以上例子中的按钮在 5000 毫秒内沿着从 x=0 到 x=450 的路径移动。 可以通过 http://localhost:8080/lps-4.0.x/animation/SimpleAnimation.lzx 执行这个例子。 图 19 显示生成的输出。

图 19. 简单的动画
一个标有文字'Animated Stuff'的按钮,箭头表示向右移动
一个标有文字'Animated Stuff'的按钮,箭头表示向右移动

多重动画

通过使用多个 animator 标记,可以使一个对象同时沿着两个以上的方向移动。 它可以一边沿着 x 轴移动,一边旋转。清单 23 显示使用多个 animator 标记的代码。

清单 23. MultipleAnimation.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
	<view width="100" height="60" align="center" valign="middle" 
		resource="IBMLogo.jpg>
		<animator attribute="x" from ="0" to="450" duration="5000"/>
		<animator attribute="rotation" to="360" duration="5000"/>
	</view>
</canvas>

上述应用程序中的按钮在 5000 毫秒内一边沿着从 x=0 到 x=450 的方向移动,一边进行 360 度的选择。可以通过浏览 http://localhost:8080/lps-4.0.x/animation/MultipleAnimation.lzx 执行上述例子。图 20 显示生成的输出。

图 20. 多重动画
运动中的 IBM logo,它一边向右移动,一边慢慢旋转
运动中的 IBM logo,它一边向右移动,一边慢慢旋转

当生成的应用程序装载后,以上例子中的动画便立即开始动起来。 另外,还可以使动画根据某个事件,例如 onClick 来开始,方法是将 animator 标记的 start 属性设为 false, 然后调用 animator 对象的 doStart 方法。 清单 24 实现了该功能。

清单 24. ManualAnimationStart.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
	<button width="100" height="60" valign="middle" 
		text="Start Animation" onclick="this.a.doStart()">
		<animator name="a" attribute="x" start="false"
			from ="0" to="450" duration="1000" motion="easein"/>
	</button>
</canvas>

可以使用 http://localhost:8080/lps-4.0.x/animation/ManualAnimationStart.lzx 编译和调用该应用程序。

重复动画

可以设置 animator 标记的 repeat 属性,以确定动画循环的次数。将该属性设为 “Infinity” 则导致动画无限循环。 例如,清单 25 中的 OpenLaszlo 应用程序显示一个重复 3 次的动画。

清单 25. RepeatAnimation.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
	<view width="100" height="60" align="center" valign="middle" 
		resource="IBMLogo.jpg>
		<animator attribute="rotation" from ="0" to="360" duration="3000" 
			repeat="3"/>
	</view>
</canvas>

使用 http://localhost:8080/lps-4.0.x/animation/RepeatAnimation.lzx 运行该例子。

清单 26 显示一个视图在另一个视图上翻滚。

清单 26. CircularAnimation.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
	<view valign="middle" align="center" bgcolor="#ddddee" width="350" height="150"/>
		<view width="40" height="40" bgcolor="silver"
			x="${ 180 + 30 * Math.cos (angle*Math.PI/180) }"
			y="${ 100 + 30 * Math.sin (angle*Math.PI/180) }">
			<attribute name="angle" value="0"/>
			<animator motion="linear" attribute="angle" from ="0"
				to="360" duration="2000" repeat="Infinity"/>
			<animator motion="linear" attribute="rotation" from ="0"
				to="360" duration="2000" repeat="Infinity"/>
	</view>
</canvas>

使用 http://localhost:8080/lps-4.0.x/animation/CircularAnimation.lzx 运行这个例子。 图 21 显示生成的输出。

图 21. 翻滚 动画
一个小正方形在一个矩形视图中翻滚
一个小正方形在一个矩形视图中翻滚

使用 animatorgroup

可以使用 animatorgroup 标记组合多个 animator 标记。 process 属性确定这些标记如何运行。将 process 属性设为 “simultaneous” 将使所有事件同时发生。将 process 设为 “sequential” 将使这些事件依次发生。默认情况下, process 属性的值为 sequential。清单 27 显示 animatorGroup 的使用。

清单 27. AnimatorGroup.lzx
<canvas height="400">
	<button width="70" text="Click here">
		<animatorgroup process="sequential">
			<animator attribute="x" from ="0" to="300" duration="1000"/>
			<animator attribute="rotation" from ="0" to="90" duration="1000"/>
		</animatorgroup>
	</button>
</canvas>

使用 timer

计时器(timer)是一个对象,通过设置计时器,可以在指定时间段过后调用某个方法。 例如,可以在用户 10 分钟无操作后调用 显示一条警告消息,如清单 28 所示。

清单 28. Timer.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
	<alert id="alertBox" width="250">10 minutes left for Completion!</alert>
	<handler name="oninit">
		var delegate = new LzDelegate (this, "showAlertBox");
		lz.Timer.addTimer (delegate, 3000);
	</handler>	
	<method name="showAlertBox">
		alertBox.open();
	</method>
</canvas>

可以使用 http://localhost:8080/lps-4.0.x/animation/Timer.lzx 编译和调用上述例子。图 22 显示生成的输出。

图 22. Timer 服务
显示'10 minuts left for Completion!'的对话框,其中有一个 OK 按钮
显示'10 minuts left for Completion!'的对话框,其中有一个 OK 按钮

清单 29 中的另一个例子显示一个数字时钟。

清单 29. DigitalClock.lzx
<canvas fontsize="45" width="450" bgcolor="#6699FF" height="200">
	<text id="display" width="250" bgcolor="#ddddee" align="center" valign="middle"/>
	<handler name="oninit">
		lz.Timer.addTimer (new LzDelegate (this, "refreshClock"), 1000);
	</handler>
	<method name="refreshClock">
		lz.Timer.addTimer (new LzDelegate (this, "refreshClock"), 1000);
		var now = new Date ();
		var hour = now.getHours ();
		var minute = now.getMinutes();
		var second = now.getSeconds();
		display.setText (hour + ":" + minute + ":" + second);
	</method>

	<![CDATA[
		if (n < 10) {
			return "0" + n;
		} else {
			return n;
		}
	]]>
</canvas>

使用 http://localhost:8080/lps-4.0.x/animation/DigitalClock.lzx 运行这个例子。图 23 显示生成的输出。

图 23. 数字时钟
时间'15:47:40'
时间'15:47:40'

构建富组件

OpenLaszlo 为用户提供了一套丰富的可直接用于 LZX 应用程序的组件。 图 24 显示 OpenLaszlo 中一些内置组件的类层次结构。

图 24. 组件 类层次结构
OpenLaszlo 的组件树
OpenLaszlo 的组件树

Slider

Slider 是一个组件,用于通过拖动按钮进行值的选择。 slider 类是所有 slider 的模板。 它是 Baseslider 的直接子类。而 Baseslider 类又扩展 Basevaluecomponent 类,后者是 Basecomponent 的直接子类。清单 30 中的代码 使用 slider 控制一个视图的透明度。

清单 30. Slider.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
	<slider name="s" valign="middle" align="center"  height="100" 
		showvalue="true" width="200" value="50"/>
</canvas>

可以使用 http://localhost:8080/lps-4.0.x/richComponents/Slider.lzx 编译和调用该应用程序。 图 25 显示生成的输出.

图 25. Slider 组件
一个居中的 slider,范围为 0 到 100
一个居中的 slider,范围为 0 到 100

datepicker

顾名思义,通过 datepicker 组件可以轻松地选择日期。 该组件由 datepicker 类表示,这个类是 Basedatepicker 类的直接子类。Basedatepicker 是一个抽象类,它是 Basecomponent 的子类。例如,清单 31 中的代码允许用户选择一个日期,并在一个文本标记中显示所选择的日期。

清单 31. Datepicker.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
	<script>
		var today = new Date ();
		var lastYear = new Date (today.getFullYear () - 1,
		today.getMonth (), today.getDate ());
		var nextYear = new Date (today.getFullYear () + 1,
		today.getMonth (), today.getDate ());
	</script>
	<simplelayout axis="y" spacing="5"/>
	<datepicker earliestdate="${lastYear}"
		selecteddate="${today}"
		latestdate="${nextYear}">
		<handler name="onselecteddate">
			if ( this.selecteddate != null ) {
				display.year.setText (
				this.selecteddate.getFullYear() );
				display.month.datapath.setXPath(
				"datepicker_strings_en:/months/month[@index='" +
				this.selecteddate.getMonth() + "']/@full" );
				display.date.setText ( this.selecteddate.getDate() );
			}
		</handler>
	</datepicker>
	<view id="display">
		<text name="month" resize="true" datapath="."/>
		s<text name="date" resize="true"/>
		<text name="year" resize="true"/>
		<simplelayout axis="x" spacing="2"/>
	</view>
</canvas>

使用 http://localhost:8080/lps-4.0.x/richComponents/DatePicker.lzx 编译和调用上述例子。 图 26 显示生成的输出。

图 26. Date picker
一个日期选择器,其中选中了 2009 年 11 月 1 日
一个日期选择器,其中选中了 2009 年 11 月 1 日

Scrollbar

scrollbar 组件由 scrollbar 类表示。这个类是 Basescrollbar 的子类,后者又是 Basecomponent 的直接子类。清单 32 中的代码显示一个 LZX 应用程序,该应用程序使用一个垂直滚动条和一个水平滚动条。

清单 32. ScrollBar.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
	<view name="main" width="100" height="100" clip="true">
		<text multiline="true">
			OpenLaszlo is an open source platform invented by Laszlo Systems, 
			a company based in San Mateo, California for the development and
			deployment of rich Internet based applications.It is released 
			under the Open Source Initiative-certified Common Public License. 
			One of the greatest challenge faced by Rich Interactive 
			Applications (RIA) developers today is that of Browser 
			Compatibility. Since OpenLaszlo is based on the famous Java 
			paradigm of write-once-run-everywhere, it ensures that 
			applications based on OpenLaszlo runs uniformly in various 
			browsers in multiple operating systems. 
		</text>
		<scrollbar axis="y"/>
		<scrollbar axis="x"/>
	</view>
</canvas>

可以使用 http://localhost:8080/lps-4.0.x/richComponents/ScrollBar.lzx 编译和调用该应用程序。 图 27 显示生成的输出。

图 27. ScrollBar
视图中有一个垂直滚动条和一个水平滚动条
视图中有一个垂直滚动条和一个水平滚动条

tab 和 Tabpane

标签(tab)是包含标签面板的视图。每个标签面板有一个标题, 其中可以容纳其他组件。标签和标签面板是在小块区域内放置组件的很好的方式,如清单 33 所示。

清单 33. TabbedPane.lzx
<canvas width="450" bgcolor="#6699FF" height="300">
	<form inset_top="10">
		<tabs tabalign="right">
			<tabpane bgcolor="silver"  text="Name" tabwidth="80">
				<simplelayout axis="y"/>
				<text>Customer Name</text>
				<edittext name="customerName"/>
				<text>Email</text>
				<edittext name="email"/>
				<radiogroup name="customerType">
					<radiobutton>Silver</radiobutton>
					<radiobutton>Gold</radiobutton>
				</radiogroup>
				<button>Submit</button>
			</tabpane>
			<tabpane bgcolor="silver" text="Address" tabwidth="80">
				<simplelayout axis="y"/>
				<text>Address</text>
				<edittext name="address"/>
				<text>City</text>
				<edittext name="city"/>
				<text>State</text>
				<edittext name="astate"/>
				<text>Pin Code</text>
				<edittext name="pincode"/>
			</tabpane>
		</tabs>
	</form>
</canvas>

浏览器 http://localhost:8080/lps-4.0.x/richComponents/TabbedPane.lzx 调用以上例子。 图 28 显示生成的输出。

图 28. TabbedPane
包含 Name 和 Address 两个标签的视图
包含 Name 和 Address 两个标签的视图

tree

树(tree)是一种 OpenLaszlo 组件,用于显示分层的数据,例如 XML。树以 tree 类表示, 这个类是 Basetree 的子类。而 Basetree 又是Basecomponent 的子类。清单 34 中的代码显示如何构造和使用树。

清单 34. TreeView.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
	<view valign="middle" align="center" width="200" height="150">
		<tree open="true" text="OpenLaszlo Article">
			<tree text="Chapter 1: Overview" isleaf="true"/>
			<tree open="true" text="Chapter 2: Basic Components">
				<tree text="Section 1: Slider" isleaf="true"/>
				<tree text="Section 2: ScrollBar" isleaf="true"/>
			</tree>
		</tree>
</view>
</canvas>

使用 http://localhost:8080/lps-4.0.x/richComponents/TreeView.lzx 运行该例子。图 29 显示生成的输出。

图 29. 树视图
一个包含文件夹、子文件夹和对象的图形化树
一个包含文件夹、子文件夹和对象的图形化树

使用 XML 数据

OpenLaszlo 可以使用 XPath 显示和操纵数据,XPath 是一种用于从 XML 文档检索数据的语言。 可以使用 LzDataset 类存放 XML 数据,以及通过 HTTP GETPOST 请求检索数据。 图 30 显示 LzDataset 类 的层次结构。

图 30. LzDataset 类层次结构
一棵以 LzNode 为根节点的树。左边的分枝包含 lzDataNode、LzDataElement 和 LzDataset

可以使用 <datapath><datapointer> 操纵数据集中的数据。

DataPath

Datapath 可用于通过 XPath 访问数据集中包含的数据。作为例子, 清单 35 显示如何使用 DataPath。

清单 35. 使用 DataPath.lzx
<canvas width="600" bgcolor="#6699FF" height="220">
	<dataset name="myData" request="true" type="http" src="data.xml"/>
	<grid height="100" valign="middle" datapath="myData:/company" 
		contentdatapath="department">
		<gridcolumn width="100">
			Name
			<text datapath="name/text ()"/>
		</gridcolumn>
		<gridcolumn width="100">
			ID
			<text datapath="id/text ()"/>
		</gridcolumn>
		<gridcolumn width="200">
			Description
			<text datapath="desc/text ()"/>
		</gridcolumn>
		<gridcolumn width="100">
			Location
			<text datapath="location/text ()"/>
		</gridcolumn>
		<gridcolumn width="70">
			<view datapath="position ()">
			<button text="delete">
				<handler name="onclick">
					parent.datapath.deleteNode ();
				</handler>
			</button>
			</view>
		</gridcolumn>
	</grid>
</canvas>

清单 36 显示 data.xml 的内容

清单 36. data.xml 的内容
<company>
	<department headCount="19">
		<name>HR</name>
		<id>Comp-HR-01</id>
		<location>First-Flr</location>
		<desc>Looks after Human resources</desc>
	</department>
	<department headCount="200">
		<name>Manufacturing</name>
		<id>Comp-MFG-02</id>
		<location>Ground-Flr</location>
		<desc>Manufactures Components</desc>
	</department>
	<department headCount="65">
		<name>Marketing</name>
		<id>Comp-Mktg-01</id>
		<location>Third-Flr</location>
		<desc>Markets the product</desc>
	</department>
</company>

可以使用 http://localhost:8080/lps-4.0.x/data/UsingDataPath.lzx 编译和调用该应用程序。图 31 显示生成的输出。

图 31. 使用 Datapath
电子表格型的数据视图
电子表格型的数据视图

DataPointer

DataPointer 用于作为数据集中的游标。 DataPointer 可用于连续地遍历数据库中的记录。 清单 37 显示如何使用 DataPointer。

清单 37. UsingDataPointer.lzx
<canvas width="450" bgcolor="#6699FF" height="200">
  <simplelayout spacing="5"/>
  <script>
    var isLast = false;
  </script>

  <dataset name="mydata" request="true" type="http" src="data.xml"/>
  
  <alert name="myalert"/>

  <view id="tt" height="60" valign="middle" width="450" font="verdana" fontsize="20">
	<text name="output" y="30" align="center"/>
  </view>

  <view height="150" align="center" valign="middle" >
    <simplelayout  axis="x" spacing="4" />
    <datapointer id="mydp" xpath="mydata:/company/department[1]"/>
    <button font="verdana" fontsize="15"> Next Record
      <handler name="onclick">
		isFirst = false;
		var s = mydp.xpathQuery('name/text()');
		if(isLast){
			s = 'Last Record!';
		}
		if(!mydp.selectNext()){
		   isLast = true;
		}
        tt.output.setText(s);
      </handler>
    </button>
  </view>
</canvas>

使用 http://localhost:8080/lps-4.0.x/data/UsingDataPointer.lzx 运行上述例子。 图 32 显示生成的输出。

图 32. 使用 DataPointer
通过一个 'Next Record' 按钮显示标题'Manufacturing'
通过一个 'Next Record' 按钮显示标题'Manufacturing'

调试

在软件开发过程中,良好的调试工具有助于让应用程序更加健壮,没有缺陷。 OpenLaszlo 附带了一个增强的调试工具,它使开发人员可以查看 运行时错误消息、查看变量值等等。

为了显示 Debugger 窗口,执行以下操作:

  • 将 canvas 标记的 debug 属性设为 true:<canvas debug="true">
  • 将查询参数 debug=true 附加到用于请求 OpenLaszlo 应用程序的 URL 的后面。例如:
    http://localhost:8080/lps-4.0.x/app14/debugTest.lzx?debug=true
  • 单击 Debug 单选按钮,并单击 Compile 按钮。

例如, 清单 38 中的代码显示一个画布中的一个按钮。

清单 38. DebugButton.lzx
<canvas width="450" bgcolor="#6699FF" height="800">
	<button id="buttonId" width="200" height="80" align="center" valign="middle">
		Hello World!!</button>
</canvas>

可以通过使用 debug=true 参数打开它的 URL,以调试的方式调用上述应用程序: http://localhost:8080/lps-4.0.x/debug/DebugButton.lzx?debug=true。 这样将装载该应用程序,并打开一个 Laszlo Debugger 窗口,窗口底部有一个输入文本框。

输入按钮 ID buttonId 并按 Enter。输入的文本将以绿色回显,调试器 将以蓝色超级链接的形式打印出该对象。

接下来,在调试器窗口中单击对象链接 <<button>#0| #buttonId>>。调试器将打印出 JavaScript 对象的属性,如下面图 33 所示。

图 33. Debugger 窗口
调试器窗口,其中列出与运行的应用程序相关联的一系列参数
调试器窗口,其中列出与运行的应用程序相关联的一系列参数

在调试器中输入一个 JavaScript 表达式,便可以编译该表达式并打印出结果。 例如,buttonId.width 将返回 width 属性的值。类似地,输入命令 buttonId.setAttribute('width', 400) 将改变画布上显示的按钮的宽度。 Debugger 窗口是 Debug 类的一个实例,后者是 LzView 的子类。 因此,LzView 类中的所有属性在 Debug 类中都可以使用。

下面是 Debug 类中定义的方法:

  • backtrace (frameCount)— 将当前调用栈的快照复制到一个 LzBacktrace 对象中,之后便可以打印或查看该对象。只有 在使用 -option debugBacktrace=true 编译应用程序时,才可以使用该方法。frameCount 参数指定回溯时跳过的帧数(默认为 1)。
  • error (control, args)— 在控制台显示一条错误。control 参数指定一个格式化控制台,args 参数表示任意数量的参数。
  • format (control, args)— 使用 formatToString 方法格式化输出。control 参数指定一个格式化控制台,args 参数表示任意数量的参数。
  • formatToString (control, args)— 该方法类似于 C 语言中的 printf 函数。control 参数指定一个格式化控制台,args 参数表示任意数量的参数。
  • inspect (object, reserved)— 在调试控制台显示指定对象的属性。 reserved 参数预留将来使用。
  • log (message)— 将消息发送到日志文件。
  • monitor (object, property)— 监视指定对象的指定属性。 每当该属性的值变化时,将在 Debugger 窗口显示一条消息。
  • trace (object, method)— 监视指定对象中指定方法的使用。 每当该方法被调用时,Debugger 窗口中将打印一条消息。
  • unmonitor (object, property)— 取消对指定对象的指定属性的监视。
  • untrace (object, method)— 取消对指定对象的指定方法的监视。

Debugger 窗口还可以用于 求 JavaScript 全局变量和表达式的值,以及执行 JavaScript 语句。求值器是 Debugger 窗口底部的文本框和 EVAL 按钮。

结束语

OpenLaszlo 是一个开放源码的开发平台, 可用于构建以 LZX 编写的富 Web 应用程序。LZX 是一种包括嵌入式 JavaScript 的 XML 语言。

但是,与很多 Ajax 解决方案不同,OpenLaszlo 应用程序可跨浏览器移植。 这要归功于 OpenLaszlo 编译器技术,OpenLaszlo 编译器负责运行时细节, 使开发人员可以将更多精力放在应用程序的行为/逻辑和外观上, 真正使它成为 “编写一次,到处运行” 的平台。OpenLaszlo 支持一个丰富的图形模型, 有很多内置的、可重用的组件,以及高级的 WYSIWYG 文本和图形化编辑工具。


下载资源


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Open source, WebSphere
ArticleID=477675
ArticleTitle=OpenLaszlo —— 一个快速构建和部署富 Internet 应用程序的平台
publish-date=03252010