Click中的Panel表示网页上一个区域,或者说是一种数据的展现格式,我们使用模板可以定义数据的具体展现格式,比如显示一个表格,或者显示成一个个的图文框等。
Click的API中还有ListPanel和TabbedPanel两种变相的Panel,实际上只是多个Panel的集合而已。
创建一个Panel
- Panel header = new Panel("header","templates/header.htm")
创建一个ListPanel,来装载多个Panel
- private ListPanel listPnl = new ListPanel("listPanel");
把多个Panel添加到ListPanel,并添加数据
- addControl(listPnl);
- listPnl.add(new Panel("header","templates/header.htm"));
- listPnl.add(new Panel("panel1","templates/panel_item1.htm"));
- listPnl.add(new Panel("panel2","templates/panel_item2.htm"));
- addModel("emps", es.getEmpList());
header.htm只是用来显示一个标题的模板
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>This is Header</title>
- <style type="text/css">
- body{
- margin:0;padding:0
- }
- .banner{
- margin:2px;border-radius:10px;
- box-shadow:0px 3px 30px rgba(0, 0, 0, 0.1) inset;
- padding:10px;
- }
- </style>
- </head>
- <body>
- <div class="banner"><h1 style="text-shadow:5px 2px 6px #000;">Apache Click - Panel & Tree</h1></div>
- </body>
- </html>
panel_item1.htm和panel_item2.htm只是数据2种不同展示模板
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <style type="text/css">
- div.box{min-width:400px;width:50%;}
- table{ width:100%;margin-left:2px;
- border-layout:fixed;
- border-collapse:collapse;
- font-size:11pt;}
- th{background:grey;
- border:1px solid black;}
- td{text-align:center;}
- </style>
- </head>
- <body>
- <div class="box">
- <table border="1">
- <thead>
- <tr><th>姓名</th><th>性别</th><th>职位</th><th>薪酬</th></tr>
- </thead>
- <tbody>
- #foreach($e in $emps)
- <tr>
- <td>$e.name</td><td>$e.gender</td>
- <td>$e.job</td><td>$e.salary</td>
- </tr>
- </tbody>
- #end
- </table>
- </div>
- </body>
- </html>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- </head>
- <body>
- #foreach($e in $emps)
- <div style="width:200px;padding:10px;float:left;margin:3px;border:1px solid grey;font-size;10pt">
- <p>姓名:$e.name</p>
- <p>性别:$e.gender</p>
- <p>职位:$e.job</p>
- <p>薪酬:$e.salary</p>
- </div>
- #end
- </body>
- </html>
我想到的ListPanel所带来的好处就是将一个也没模块化,从而提高各模块的重用。当然,这其中也包含了设计的灵活性。
最终,我顺利的得到了效果。
接着,我又做了一个Tree的小例子。如果大家不觉得烦,那就继续看吧。。
Tree是一个相对复杂的组件,如果不是得益于Apache,我们可能要做得更多。
创建一个Tree(为了尽量和Panel的界面风格相似,我重用了header.htm来渲染我的标题,我所要做的就是在网页上边添加一个panel而已)
- public TreeDemo(){
- tree = createCategoryTree();
- addControl(new Panel("header", "templates/header.htm"));
- addControl(tree);
- }
下面我创建了一个购物网站的关于手机的分类
- private Tree createCategoryTree(){
- tree = new Tree("category_tree");
- TreeNode rootNode = (TreeNode)getContext().getSession().getAttribute("treeNodes");
- if(rootNode != null){
- tree.setRootNode(rootNode);
- tree.expand(rootNode);
- return tree;
- }
- rootNode = new TreeNode("root");
- TreeNode phone = new TreeNode("手机", "1");
- rootNode.add(phone);
-
- phone.add(new TreeNode("HTC", "101", false));
- phone.add(new TreeNode("三星", "102"));
- phone.add(new TreeNode("摩托罗拉", "103"));
- phone.add(new TreeNode("诺基亚", "104"));
- phone.add(new TreeNode("索尼爱立信", "105"));
- phone.add(new TreeNode("LG", "106"));
- phone.add(new TreeNode("飞利浦", "107"));
-
- TreeNode phone_accessories = new TreeNode("手机配件","2");
- rootNode.add(phone_accessories);
-
- phone_accessories.add(new TreeNode("电池", "201"));
- phone_accessories.add(new TreeNode("充电器", "202"));
- phone_accessories.add(new TreeNode("贴膜", "203"));
- phone_accessories.add(new TreeNode("保护套", "204"));
- phone_accessories.add(new TreeNode("耳机", "205"));
- phone_accessories.add(new TreeNode("存储卡", "206"));
-
- tree.setRootNode(rootNode);
- tree.expand(rootNode);
-
- if(tree.getRootNode()!=null){
- getContext().getSession().setAttribute("treeNodes",rootNode);
- }
- return tree;
- }
然后我在htm中写入刚刚创建的Tree的名字$category_tree,它就显示出来了,虽然外貌不佳,但是我看到API中有可以设置图标的地方。
之后,我发现,Click的Tree组件的节点时可以多选的,并且可以通过API来获取所中的所有节点和展开的节点。首先这需要处理页面的请求,官方是通过重写Page中的onGet方法来完成的。下面的代码,我稍微扩展了一些。我将每次点击的节点名字放入到一个ArrayList ,并判断是选中还是非选中,分别进行添加和移除操作,最后把这个ArrayList放入到session中,以保持状态到下次点击时。
- @Override
- public void onGet() {
- String selectedId = getContext().getRequestParameter(Tree.SELECT_TREE_NODE_PARAM);
- String expandedId = getContext().getRequestParameter(Tree.EXPAND_TREE_NODE_PARAM);
- ArrayList<Object> selected = (ArrayList<Object>)getContext().getSession().getAttribute("selected");
- ArrayList<Object> expanded = (ArrayList<Object>)getContext().getSession().getAttribute("expanded");
- if(selected == null){
- selected = new ArrayList<Object>(0);
- }
- if(expanded == null){
- expanded = new ArrayList<Object>(0);
- }
- if(selectedId!=null){
- TreeNode selectedNode = tree.find(selectedId);
- Object val = selectedNode.getValue();
- if(selectedNode.isSelected()){
- selected.add(val);
- }else{
- selected.remove(val);
- }
- getContext().getSession().setAttribute("selected", selected);
- }
- if(expandedId!=null){
- TreeNode expandedNode = tree.find(expandedId);
- Object val = expandedNode.getValue();
- if(expandedNode.isExpanded()){
- expanded.add(val);
- }else{
- expanded.remove(val);
- }
- getContext().getSession().setAttribute("expanded", expanded);
- }
- addModel("selected", selected);
- addModel("expanded", expanded);
- }
最后,我对treeDemo.htm进行简单布局,目的就是让所有的选项都干净地列举出来。
treeDemo.htm:
- <div class="box">
- <div class="header">$header</div>
- <div class="left_box">$category_tree</div>
- <div class="right_box">
- #if($expanded)
- <div class="category_box">
- <div class="category_title">类别:</div>
- <div class="category_selected">
- #foreach($eid in $expanded)
- <a href="#" class="item">$eid</a>
- #end
- </div>
- <div class="blank"></div>
- </div>
- #end
- #if($selected)
- <div class="category_box">
- <div class="category_title">已选:</div>
- <div class="category_selected">
- #foreach($sid in $selected)
- <a href="#" class="item">$sid</a>
- #end
- </div>
- <div class="blank"></div>
- </div>
- #end
- </div>
- </div>
最终的效果有点原始~
不知不觉,快要下班了,今天周五,周末愉快~