Readers: 20 | Updated: 2008

tapestry的列表

Translate Into:

网站: JavaEye  作者: summerkai  链接:http://summerkai.javaeye.com/blog/177738  发表时间: 2008年03月30日

声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!


tapestry的列表有两种,一种是ForEach。一种是Table。第一种是只需要tapestry的主包就好的。另一种是需要contrib附加包的。

ForEach是普通的列表。如果需要一大片的表数据显示,就可以用这个来搞定。

要模拟表,首先要有点数据吧!模拟一个数据库,最简单的就是建立静态的类变量。我们可以这样定义一个水果列表类:

package com.bo;

import java.util.ArrayList;
import java.util.List;

public class MyFruitList {

    private static List<Fruit> fruitList;
    
    public static List<Fruit> getFruitList(){
        if(fruitList == null){
            fruitList = new ArrayList<Fruit>();
            fruitList.add(getFruit(1,"apple"));
            fruitList.add(getFruit(2,"orangle"));
            fruitList.add(getFruit(3,"orangle1"));
            fruitList.add(getFruit(4,"orangle2"));
            fruitList.add(getFruit(5,"orangle3"));
            fruitList.add(getFruit(6,"orangle4"));
        }
        return fruitList;
    }
   
    public static void addFruit(Fruit f){
        fruitList.add(getFruit(f.getId(),f.getName()));
    }
   
    public static Fruit getFruit(int id,String name){
        Fruit f = new Fruit();
        f.setId(id);
        f.setName(name);
        return f;
    }
}

定义个全局的静态的Fruit的List,用getFruitList模拟数据库中取数据。

然后在html模板中画个表格:

<table width="183" height="73" border="1">
                <tbody>
                    <tr>
                        <td>
                            id
                            <br>
                        </td>
                        <td>
                            name
                            <br>
                        </td>
                    </tr>
                    <tr jwcid="fruitListLoop">
                        <td>
                            <span jwcid="fruitId">fid</span>
                        </td>
                        <td>
                            <span jwcid="fruitName">fname</span>
                        </td>
                    </tr>
                </tbody>
            </table>

和普通表格比,多了几个jwcid属性。这就是tapestry网页模板和普通html的区别。也就是要在page文件中定义关联和规则的东西。还有几个span,这是用来绑定字段用的。

为了看动态效果,我们再加一个按钮,按它,就在表下面添加一行。

<input type="submit" value="add" jwcid="addBut"/>

好了,开始写page:

首先绑定addBut按钮:
<component id="addBut" type="Submit">
        <binding name="listener" expression="listeners.addSubmit"/>
    </component>

然后绑定表数据:
<property-specification name="fruitList" type="java.util.List"/>
    <property-specification name="fruit"
        type="com.bo.Fruit"/>

这里绑定了两个类,一个是List类型的列表,其中放各种Fruit数据,模拟数据库中选择出来的Recordset。一个是Fruit类型的fruit,这个是用来表示List中的一条记录。相当于一个Row,之所以定义它,是下面的定义要引用到它。

定义表数据源:
<component id="fruitListLoop" type="Foreach">
        <binding name="source" expression="fruitList"/>
        <binding name="value" expression="fruit"/>
        <static-binding name="element" value="tr"/>
    </component>
这里定义了整个表的数据源对应。source绑定了上面定义的List。value绑定了上面定义的Row记录。element绑定了标签。注意这里element绑定的写法tap3和tap4不一样,4中是这样写:
<binding name="element" value="literal:tr">


绑定表的字段:
<component id="fruitId" type="Insert">
        <binding name="value" expression="fruit.id"/>
    </component>
    <component id="fruitName" type="Insert">
        <binding name="value" expression="fruit.name"/>
    </component>
这里的expression就把值字段绑定到html模板的相应td标签的span中。每插入一个fruit,就按照绑定的变量到fruit中取出,然后塞入对应的span中。

最后要在HOME中添加对Add按钮的绑定方法。

先添加定义

public abstract List<Fruit> getFruitList();
   
public abstract void setFruitList(List<Fruit> fl);

这两个数据用来定义对列表数据源的读取。表格里显示什么数据,主要由getFruitList中读取的数据来定。这里要注意一下pageBeginRender的问题。在页面重新载入的时候,都要运行pageBeginRender。然后根据当前数据来打印html。因为submit后都要重载页面,所以每次重载页面,都需要重新从数据库中读取数据。然后用setFruitList设置到页面中。

public void pageBeginRender(PageEvent event) {
        if(getUInfo()==null){
            setUInfo(new UserInfo());
        }
        if(getFruitList()==null){
            List<Fruit> fruitList = MyFruitList.getFruitList();
            setFruitList(fruitList);
        }
    }

现在绑定addSubmit方法:

public void addSubmit(IRequestCycle cycle){
        MyFruitList.addFruit(MyFruitList.getFruit(++i,"apple"+i));
    }

在全局变量中添加数据,就相当于在数据库中添加一行。那么为什么没有再用setFruitList呢?这里addSubmit响应后直接就重新刷新页面,然后又到pageBeginRender重读全局变量,所以这里的setFruitList根本没有用(在没设置fruitList的作用域的情况下——因为我没有设置fruitList的作用域)。

当然这里用到一个自加的i,所以要在类中添加一行:

private int i=12;//从12开始。

好了,ForEach差不多就这样。

Table和ForEach的区别就是Table是分页的。而且需要添加contrib额外的支持

打开WEB-INF下的application文件,添加一行:

<library id="contrib"
        specification-path="/org/apache/tapestry/contrib/Contrib.library"/>

一定要添加这行,不然page会提示contrib名字空间无效。

然后设计Html模板,添加一个table,像这样。

<table jwcid="tableView" width="483" height="73" border="2">
                <tbody>
                    <tr>
                        <span jwcid="tableColumns">
                        <td>
                            id
                            <br>
                        </td>
                        <td>
                            name
                            <br>
                        </td>
                        </span>
                    </tr>
                    <tr jwcid="tableRows">
                        <span jwcid="tableValues">
                        <td>
                            fid
                        </td>
                        <td>
                            fname
                        </td>
                        </span>
                    </tr>
                    <tr>
                        <td colspan="6" align="center">
                            <span jwcid="condPages"><span jwcid="tablePages">1
                                    2 3 页</span> </span>
                        </td>
                    </tr>
                </tbody>
            </table>

注意那几个jwcid。一个放在table,一个放在表头tr下的span中,一个放在数据tr中一个放在数据tr的span中,两个放在翻页行的td内容的span中。

然后在page文件中添加:

对TableView数据源的绑定:
<!--TABLE控件的使用-->
    <component id="tableView" type="contrib:TableView">
        <binding name="source" expression="tableViewModel"/>
        <static-binding name="columns"
            value="id:id:id,name:名称:name"/>
        <static-binding name="pageSize" value="5"/>
    </component>
这里的tableViewModel对应的是java类里的getTableViewModel方法,columns定义的是表头,用逗号隔开每个表头定义,用:隔开表头的属性定义(有三个,具体可以看这里http://tapestry.apache.org/tapestry4/tapestry-contrib/ComponentReference/TableView.html#Examples)。pageSize定义一个页面有几条记录,以便分页。

对表头,每行,列值的定义
    <!--表头部-->
    <component id="tableColumns" type="contrib:TableColumns">
    </component>
    <!--每一行-->
    <component id="tableRows" type="contrib:TableRows">
    </component>
    <!--列值-->
    <component id="tableValues" type="contrib:TableValues">
    </component>
   
对分页的格式定义(类似google下面的圈圈,挺好理解的)
    <!--分页导航栏-->
    <component id="condPages" type="Conditional">
        <binding name="condition"
            expression="components.tableView.tableModel.pageCount > 1"/>
    </component>
    <component id="tablePages" type="contrib:TablePages">
        <static-binding name="pagesDisplayed" value="10"/>
    </component>

最主要的来了,回到Home类,要使用Table,就要实现一个方法getTableViewModel,而Table似乎不需要在page里面定义变量:
public IBasicTableModel getTableViewModel() {
        return new IBasicTableModel() {

            private int rowCount;

            public Iterator getCurrentPageRows(int start, int length,
                    ITableColumn itablecolumn, boolean flag) {
                String sortColumn = null;
                if (itablecolumn != null) {
                    sortColumn = itablecolumn.getColumnName();
                }
                return MyFruitList.getFruitList(start,length).iterator();
            }

            public int getRowCount() {
               
                return MyFruitList.getFruitList().size();
            }
        };
    }

IBaseTableModel有两个函数,一个是getCurrentPageRows,这个是返回分页当前页的数据。是由start和length控制打印起始以及条数。所以我们不能用MyFruitList.getFruitList()获取所有条目(当然这样也可以,我试过,不过没有分页效果)所以要在MyFruitList重载getFruitList方法来获取某几条记录。

public static List<Fruit> getFruitList(int start, int len){
        List<Fruit> fl = new ArrayList<Fruit>();
        int length = start+len>fruitList.size()?fruitList.size():start+len;
        for(int i=start;i<length;i++)
            fl.add(fruitList.get(i));
       
        return fl;
    }

getRowCount函数是获取总的记录条数。这就不说了。

因为用的是同一个数据(MyFruitList),所以点击addSubmit的时候,两个都可以刷新。多刷几次,分页效果就出来了。
本文的讨论也很精彩,浏览讨论>>


JavaEye推荐



From The Blogs

Life, Health, Furnishings

2008
怎样变得大胆
你认为自己是个胆大的人吗?你会怎样描述一个胆大的人呢? 查看全文

Life, Health, Furnishings

2008
三项敲定计划任务列表
明天是世界博客日,今天我就来灌灌每周“三项”!这个星期我十分努力地调控我的计划任务列表。我从博友吉恩那得到启示,一直致力于潜力任务列表而非增加大量的条项。 查看全文

The London Traveler

2008
Tapestry but not as we know it
I still remember the first time I saw a really great tapestry. It was the central panel of the Lady and the Unicorn series in the Musee de Cluny, in Paris, and I must have stood in front of it for hal... 查看全文

Personal Growth, Career Planning

2008
韶华易逝,烦恼勿寻
我是个列表专业户。从日用杂货到备忘录,我都会记下来。我倒是不介意便条是否工整美观。信封背面或者一张小纸片都可以拿来写。我最喜欢列的表格是:生命短暂,所以没有必要去……每次仔细地回看这些列表时,旧时的记... 查看全文

Film School Rejects

2008
Rumor: Animated Anubis Tapestry Coming?
In a rare occurrence, a rumor has began circulating around the web about a possible new animated feature from the Academy Award winning team of Blue Sky Studios.Blue Sky, a subsidiary of Fox, was the ... 查看全文

/Film

2008
Rumor: After the Ice Age… Blue Sky Options The Anubis Tapestry?
One of our Hollywood Spies sent us this juicy scoop, and while Im still unable to 100% confirm this story, its worth throwing out there. Rumor has it that Blue Sky Studios, the Academy Award winning c... 查看全文

天涯海阁

2008
Web2.0网站列表:在线图片存储分享服务网站
我在前面和大家分享过一些在线图片编辑服务网站,今天和大家分享一些我了解的在天涯海阁上面介绍过的在线图片存储分享服务网站,目前这类网站非常多,在这里和大家整理和分享的是一个不完全列表,大家可以来留言完善... 查看全文

月光博客

2008
使用Google Gears的网站应用列表
据GOS报道,Google Gears做为2007年的一个创新产品,令人失望的是目前只有极少数的应用程序使用了Google的这项技术,Google Gears仍然是一个早期的产品,大多数文章提到Goo... 查看全文

天涯海阁

2008
Web2.0网站列表:网络操作系统(WebOS)服务网站
WebOS(Web-based Operating System)或者称为网络操作系统,是一种基于浏览器的虚拟的操作系统,用户通过浏览器可以在这个WebOS上运用基于Web的在线应用(Web Appl... 查看全文

Music in Style

2008
Coldplay的曲目列表,枪花的新专辑,And So On..
Coldplay新专辑曲目列表公布VivaLaVida将有十首新歌Apr11,2008FROM:NMEColdplay已经公布了官方的新专辑曲目.整张专辑曲目如下:LifeInTechnicolorC... 查看全文
More Articles