分享
 
 
 

Openlaszlo开发之高级篇-自定义组件

王朝other·作者佚名  2006-08-24
窄屏简体版  字體: |||超大  

在laszlo应用开发过程中,大部分编码过程集中在对系统组件的熟练应用,比如取值、传值、刷新组件状态等等。但是很多情况下,尤其是项目的初始编码阶段,需要定义一些满足项目特定要求的界面组件,这就需要自定义组件了。

自定义组件开发,首先需要对lzx的语法、系统组件结构、开发文档有全面而且深刻的理解,然后通过不断的锻炼,按照由间到繁的实践过程,才能逐渐成为开发高手。

1. 理解组件的基本原理

原理介绍:类、模型、视图、控制器(MVC)

1.1 class与组件

LZX语言是一种面向对象的、基于原型的编程语言,而class是LZX编程语言的核心,使用class你可以生成定制的、可重用的组件来提高代码编写效率。(LZX is an object-oriented, prototype based language that allows you to create custom, reusable classes to streamline and minimize code. Classes are at the heart of LZX programming.)

下面看看一个简单的class:

<class name="MyClass" width="80" height="25" bgcolor="#CFD9AB">

<text align="center" valign="middle">Hello, World!</text>

</class>

这就定义了一个简单的class,class在LZX语法中继承自LzView,所以它可以有高度、宽度、背景色等属性。

在canvas里这样使用它:

<MyClass name="myFirstInstance"/>

就是说,把已经定义的类名当作一个标签的名称,放在canvas里就可以了,如果你愿意,可以给它起个实例名比如myFirstInstance,还可以指定它的位置等等。

(详见Software Engineer's Guide:Chapter 12. Introduction to Classes and Object Oriented Programming)

这是一个简单的class,但也是一个简单的组件,如果把这个class扩展一下,添加一些属性、事件、数据模型,那么它就可以构成一个可重用的组件。

1.2 解析LzButton

一个功能完整的组件应该由3个部分组成:M、V、C

M: A model that represents the data for the application

V: The view that is the visual representation of that data.

C: A controller that takes user input on the view and translates that to changes in the model.

(引自"A Swing Architecture Overview")

(http://java.sun.com/products/jfc/tsc/articles/architecture/index.html)

M表示模型,模型代表着组件的数据内容

V表示视图,视图代表着组件的视觉形象

C表示控制器,控制器接收用户输入并对其做出响应

下面看看一个Openlaszlo系统组件中最常用也是最简单的一个组件:button

打开C:\Program Files\OpenLaszlo Server 3.3\Server\lps-3.3\lps\components\lz 下面的button.lzx

会看到3个<include/>标签,这是button组件需要的父类组件。

接下来的<resource/>是button组件需要的视图资源,大多是flash图片背景。

注意第34行:<class name="button" extends="basebutton" ...这才是组件真正定义的开始。可以看出button继承自父类basebutton,也就是说button的基本行为来自于basebutton,basebutton定义了button组件的基础控制部分,即MVC中的C。

接下来是一些属性定义:<attribute name="someproperty" value="valuecorresponding"/>name表示属性名称,value是对应的值;

这些attribute标签是组件需要的属性,这些属性一般都要默认的值,如果需要修改,在使用组件时重载这些属性就可以了。

接下来这些<method name="".../>代表组件的C,即控制部分。

最后是<view name=""...,这些代表组件的V,视图部分。前面定义的resource,在这里用到。

因为按钮组件不需要数据来填充,也就是说它不是用来展现数据,所以就没有M,模型部分。

1.3 解析List

list组件和button组件不同的地方在于它有对其内部数据进行操作的部分,即model,M。还是在刚才的目录打开源文件list.lzx,

在第9行:<class name="list" extends="baselist"...,可以看出list也是继承自其父类baselist.lzx,即list组件的控制部分。

当然基础组件的定义,不完全是控制部分,也包含部分模型部分,但是组件的定义则包含了M、V、C三个部分。

比如baselist.lzx中,<method name="getSelection">

<method name="getNumItems">

<method name="getItemAt" args="index" >

<method name="getItem" args="value">

<method name="addItem" args="text, value" >

<method name="removeItem" args="value" >

.....

这些都是属于数据操作部分,也定义在了父类中,这个没有严格区分。

而在list.lzx中,数据操作,只定义了<method name="addItem" args="txt, val" >也是重载了父类的方法

通过super.addItem(txt,val);来重新定义了。

2. 制作一个简单的自定义button

通过了解系统组件的结构,看来自定义一个组件也不是什么难事了,如何下手做呢,还是找个例子先。

打开参考文档:http://127.0.0.1:8080/lps-3.3/docs/reference/html-index.html

找到Base Classes,第一个就是basebutton,点击,查看说明文档和例子,原来这么简单,只要给basebutton加上资源

就是一个按钮了,那么自己再修改一下不就是自己想要的按钮了吗?

首先,按钮文字是必须要加的,那么需要一个属性来保存文本字符:

<attribute name="text" type="html" value=""/>

然后需要一个text组件来显示按钮文字:

<text name="txt" align="center" valign="middle" resize="true" fgcolor="#333333" text="${parent.text}"/>

接下来,需要添加鼠标事件,来让按钮上的文字做出点击响应:

<method event="onmousedown">

txt.setX(txt.x+1);

txt.setY(txt.y+1);

</method>

<method event="onmouseup">

txt.setX(txt.x-1);

txt.setY(txt.y-1);

</method>

这样就完成了一个具备基本功能的按钮了:

<class name="mybutton" width="76" height="24" extends="basebutton" resource="longbtn_rsc">

<attribute name="text" type="html" value=""/>

<text name="txt" align="center" valign="middle" resize="true" fgcolor="#333333" text="${parent.text}"/>

<method event="onmousedown">

txt.setX(txt.x+1);

txt.setY(txt.y+1);

</method>

<method event="onmouseup">

txt.setX(txt.x-1);

txt.setY(txt.y-1);

</method>

</class>

在canvas里,通过<mybutton name="buttonname" text="clickMe">

<handler name="onclick">

//do something;

</handler>

</mybutton>

就可以使用了。

3. 扩展一个系统组件

在开发RIA项目时,往往会遇到比较复杂的业务需求,或者大数据量展现等任务,这时,能满足这些任务的组件

就显得分外重要。笔者在开发第一个任务时,需要在tree组件上进行操作,而这个tree的节点又很多,视图的

渲染过程往往花费十几秒以上,有时竟然让IE崩溃,郁闷之极。

幸得网友的指点,找到一个lazytree组件,才解决了这个问题。这是一个扩展了系统tree组件功能的组件,

它重载了tree节点生成的过程,由原来得一次全部生成,变成逐步生成,大大降低了初始渲染时间。

<class name="lazytree" extends="tree">

<!-- Turn off auto-recursion for tree. Get child nodes when tree is opened. -->

<attribute name="recurse" value="false" type="boolean"/>

<attribute name="haveChildren" value="false" type="boolean"/>

<method event="onopen" args="o"><![CDATA[

// If we already have children, don't fetch them again.

if (this.haveChildren) return;

if (o) {

// Now set recurse to true. This value is used in basetree's

// createChildTrees() method. See

// lps/components/base/basetree.lzx for and

// lps/components/lz/treee.lzx source code.

this.setAttribute('recurse', true);

createChildTrees();

this.setAttribute('recurse', false);

// We have child nodes.

this.setAttribute('haveChildren', true);

}

]]></method>

</class>

如注释所书,Turn off auto-recursion for tree. Get child nodes when tree is opened,关闭了自动递归过程

只有当前节点打开时,生成下一级节点。

由此可见,理解系统组件的结构和原理,是何等重要!

4. 开发高级的自定义组件

表格是界面开发常用的组件,但是laszlo的grid不够漂亮和精练,所以构建自己的grid就显得必要了。

以openria网站的资源下载表格为例,需要5列,而且有一列要能提供下载内容的点击操作,经过构思,步骤如下:

第一步:构建表格体包括表头和表体

<view name="header"...

<text x="0" text="ID" />

<text x="40" text="名称" />

<text x="174" text="描述" />

<text x="344" text="分类"/>

<text x="434" text="链接" />

</view>

<view name="rowcontainer"...

<view name="columns"...

...

</view>

第二步:构建表格头背景和表格体中的行

表头背景:

<view name="bg" width="$once{parent.width}"...

<view name="whitebg" x="1" y="1"...

动态行:

<view name="columns" datapath="${parent.datapath}" width="$once{parent.width-2}">

<simplelayout axis="y" spacing="1"/>

<view datapath="*"...

<text x="0" datapath="@id" width="38"/>

<text x="40" datapath="@name" width="130"/>

...

</view>

第三步:添加事件和滚动条

<text x="434" datapath="@status" width="80" fgcolor="#0000ff">

<method event="onclick">

</method>

<method event="onmouseover">

</method>

<method event="onmouseout">

</method>

</text>

滚动条: <scrollbar/>

最后完成的组件代码是:

<class name="downloadgrid" datapath="" width="510" height="200">

<view name="bg" width="$once{parent.width}" height="$once{parent.height}" bgcolor="#666666"/>

<view name="whitebg" x="1" y="1" width="$once{parent.width-2}" height="$once{parent.height-2}" bgcolor="#FFFFFF"/>

<view name="header" x="1" y="2" width="$once{parent.width-2}" height="18" bgcolor="#87CEFA">

<text x="0" text="ID" />

<text x="40" text="名称" />

<text x="174" text="描述" />

<text x="344" text="分类"/>

<text x="434" text="链接" />

</view>

<view name="rowcontainer" x="1" y="20" datapath="${parent.datapath}" width="$once{parent.width-2}" height="$once{parent.height-22}" clip="true">

<view name="columns" datapath="${parent.datapath}" width="$once{parent.width-2}">

<simplelayout axis="y" spacing="1"/>

<view datapath="*" width="$once{parent.width}" height="18" bgcolor="#F5F5F5">

<text x="0" datapath="@id" width="38"/>

<text x="40" datapath="@name" width="130"/>

<text x="174" datapath="@describe" width="166"/>

<text x="344" datapath="@category" width="76"/>

<text x="434" datapath="@status" width="80" fgcolor="#0000ff">

<method event="onclick">

var hashref = parent.datapath.p.hasAttr('href');

if(hashref){

var address = parent.datapath.p.getAttr('href');

LzBrowser.loadURL(address, '_blank')

}

</method>

<method event="onmouseover">

this.setColor(0x000000);

</method>

<method event="onmouseout">

this.setColor(0x0000FF);

</method>

</text>

</view>

</view>

<scrollbar/>

</view>

</class>

5. 总结

组件是laszlo应用的重要组成部分,每次的项目开发都会涉及到组件的开发,而且关系到项目产品的质量和效果,这也是考验一个RIA开发人员水平的重要依据,laszlo的demo中有很多值得研究的组件,网上也有开发人员的作品供大家分享,每次openlaszlo新版本的发布都会有新的组件添加进来,这要感谢众多contributor的慷慨,开源软件正是在这种开放的环境中不断成长起来的,让我们写好laszlo组件,共同促进RIA的发展。

一年前的今天,我在RIACN上发了一帖,倡导志愿者共同推广openlaszlo技术,到今天为止,开源富客户网络仍然差一部分没能做完,写这篇文章,仅此补偿当初的豪情壮志。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有