加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

java+ztree实现两棵树之间的相互移动

(2012-07-18 10:45:35)
标签:

杂谈

分类: 我的IT之路

因为一个项目的需要,在网上找了点资料,花了两天的时间终于完成了,感谢资料分享的朋友,现在也将自己的实现并结合别人资料整理如下:

1.所需要的准备工作,导入jquery-1.7.2.js,jquery-ztree-2.5.js,zTreeStyle.css,这些东西有需要的朋友可以给我留言;

2.ztree需要的数据格式var datad=[{"code":"12-10","id":1200001,"name":"资金业务","nodes":[{"code":"12-10-10","id":1200015,"name":"资金划拨策略定义","nodes":[],"privilegeUrl":"/gather/view/v001.jsp","systemModuleID":12},{"code":"12-10-20","id":1200014,"name":"资金上划设置","nodes":[],"privilegeUrl":"/gather/view/v013.jsp","systemModuleID":12},{"code":"12-10-30","id":1200021,"name":"资金下拨设置","nodes":[],"privilegeUrl":"/gather/view/v052.jsp","systemModuleID":12},{"code":"12-10-40","id":1200018,"name":"手动上划","nodes":[],"privilegeUrl":"/gather/view/v030.jsp","systemModuleID":12},{"code":"12-10-50","id":1200022,"name":"手动下拨","nodes":[],"privilegeUrl":"/gather/view/v040.jsp","systemModuleID":12},{"code":"12-10-60","id":1200019,"name":"划拨结果查询","nodes":[],"privilegeUrl":"/gather/view/v060.jsp","systemModuleID":12},{"code":"12-10-70","id":1200017,"name":"银行调账","nodes":[],"privilegeUrl":"/gather/view/v020.jsp","systemModuleID":12}],"privilegeUrl":"","systemModuleID":12}];

3.jsp页面

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>选择公告发布单位</title>
 <link rel="stylesheet" href="../zTreeStyle/zTreeStyle.css" type="text/css">
 <script type="text/javascript" src="../js/jquery-1.7.2.js"></script>
 <script type="text/javascript" src="../js/jquery-ztree-2.5.js"></script>
 <style>
  TR {background-color:#FAFAFA;}
  body {background-color: white;margin:1; padding:1;text-align: center;}
  div, p, table, th, td {list-style:none;margin:0; padding:0;color:#333;font-size:12px;font-family:dotum, Verdana, Arial, Helvetica, AppleGothic, sans-serif;}
 </style>
 <script type="text/javascript">
 var datad=[${jsonString}];
 var setting = {
   checkable: true
  };
  //数据右移动
  function addRole() {
    //移动方法
    //右移时Tree1 在第一个参数,Tree2第二个参数
    //表示Tree1移动致Tree2
    moveTreeNode(Tree1, Tree2);
    
  }
  
  //数据左移动
  function delRole() {
   //移动方法 参数相反
   moveTreeNode(Tree2, Tree1);
  }
  
  function moveTreeNode(zTree1, zTree2){
   var nodes = zTree1.getCheckedNodes(); //获取选中需要移动的数据
   for(var i=0;i<nodes.length;i++){   //把选中的数据从根开始一条一条往右添加
    var node = nodes[i];
    
    var strs={};   //新建一个JSON 格式数据,表示为一个节点,可以是根也可以是叶
    strs.id =node.id;
    strs.name=node.name;
    strs.code= node.code;
    strs.nodes = new Array(); //树节点里面有个 nodes 集合,用来存储父子之间的包涵关系
    
    //调用添加方法
    //strs : json 格式..拼装成树的一个节点
    //zTree2: 表示需要添加节点的树
    zTreeDataAddNode(strs,zTree2);
    
    //获取这个被添加的code 如果是右增加  用来把它从左边移除掉
    var scode = strs.code;
      scode = scode.substring(0, scode.lastIndexOf("-"));
    
    //使用递归移除 移除的时候从叶子开始找  和增加的时候刚好相反
    //参数1就是数组最后一个数据 
    //scode  : 上面截取的code 表示父亲节点
    //zTree1 : 需要移除的树,在zTree1 里面移除此对象
    zTreeDataDelete(nodes[nodes.length-(i+1)],scode,zTree1);
    }
    //把选中状态改为未选择
    zTree2.checkAllNodes(false); 
    zTree1.checkAllNodes(false);
    
    //刷新
    zTree2.refresh();
    zTree1.refresh();
  }
  
  //树数据移动方法
  function zTreeDataAddNode(strs,zTree2){
   var nodes = zTree2.transformToArray(zTree2.getNodes()); //获取需要添加数据的树下面所有节点数据
   
   //如果有多个数据需要遍历,找到strs 属于那个父亲节点下面的元素.然后把自己添加进去
   if(nodes.length > 0){
    
    //这个循环判断是否已经存在,true表示不存在可以添加,false存在不能添加
    var isadd=true;
    for(var j=0;j<nodes.length;j++){
      if(strs.code==nodes[j].code){
       isadd=false;
       break;
      }
    }
    
    //找到父亲节点
    var scode = strs.code;
    scode = scode.substring(0, scode.lastIndexOf("-"));
    var i=0;
    var flag =false;
    for(i ;i<nodes.length;i++){
     if(scode ==nodes[i].code){
      flag = true;
      break;
     }
    }
    
    //同时满足两个条件就加进去,就是加到父亲节点下面去
    if(flag && isadd){
      var treeNode1=nodes[i];
      treeNode1.nodes[treeNode1.nodes.length <=0 ? 0 : treeNode1.nodes.length++]=strs;
      
    //如果zTree2 里面找不到,也找不到父亲节点.就把自己作为一个根add进去
    }else if(isadd){
      zTree2.addNodes(null,strs);
     }
   }else{
      //树没任何数据时,第一个被加进来的元素
      zTree2.addNodes(null,strs);
   }
  }
  
  //数据移除
  function zTreeDataDelete(node,scode,zTree1){
   if(node.isParent){ //判断是不是一个根节点,如果是一个根几点从叶子开始遍历寻找
    
    //如果是个根就检测nodes里面是否有数据
     if(node.nodes.length > 0){
        //取出来
        var fnodes  = node.nodes;
        for(var x = 0; x<fnodes.length; x++){
         //不是根节点.并且code 相当就是需要移除的元素
         if(!(fnodes[x].isParent) && fnodes[x].code==scode){ 
           //调用ztree 的移除方法,参数是一个节点json格式数据
           zTree1.removeNode(fnodes[x]);
           
           //如果当前这个节点又是个根节点.开始递归
         }else if(fnodes[x].isParent){ 
           zTreeDataDelete(fnodes[x],scode);
         }
        }
      }else{
        //如果是个根,但是下面的元素没有了.就把这个根移除掉
        zTree1.removeNode(node);
      }
    }else{
     //不是就直接移除
     zTree1.removeNode(node);
    }
  }
  
  //zTree说明:
  //这里没有样式之类的东西,需要看到还需要引人几个css 和 imp 之类的东西.
  //可以去看zTree的demo 和 API
  
  //初始化方法
  $(document).ready(function(){
   //树1 数据 生成
   Tree1 = $("#srcTree").zTree(setting, datad); 
   //树2 数据null
   Tree2 = $("#tarTree").zTree(setting, null);
  });
  function getData(){
  var nodes = Tree2.transformToArray(Tree2.getNodes()); //获取需要添加数据的树下面所有节点数据
   
   //如果有多个数据需要遍历,找到strs 属于那个父亲节点下面的元素.然后把自己添加进去
   var values="";
   if(nodes.length > 0){
    //这个循环判断是否已经存在,true表示不存在可以添加,false存在不能添加
    for(var j=0;j<nodes.length;j++){
      //alert("nodename:"+nodes[j].name);
      values=values+nodes[j].name+","
    }
   }
   window.returnValue=values;
   window.close();
  }
 </script>
  </head>
 
  <body>
   <table width="800px" height="80%" cellspacing="1" cellpadding="3" align="center" border="0" bgColor="#000000">
     <tr>
      <td align="left" valign="top" width="40%" id="td_tree1">
    <ul id="srcTree" class="tree" style="width:100%; overflow:auto;"></ul>
   </td>
      <td align="center" valign="middle" width="10%">
      <button id="btnadd" onclick="addRole()">》》</button><br><br><br>
      <button id="bendel" onclick="delRole()">《《</button>
      </td>
      
      <td align="left" valign="top" width="40%" id="td_tree2">
    <ul id="tarTree" class="tree" style="width:100%; overflow:auto;"></ul>
   </td>
     </tr>
     <tr height="20px">
      <td colspan="3" align="center" valign="middle">
       <button onclick="window.location.href='Interaction.do?action=selectData';">刷新数据</button>&nbsp;&nbsp;&nbsp;<button onclick="getData();">保存数据</button>
      </td>
     </tr>
    </table>
  </body>
</html>

4.接下来就是后台代码拼凑需要的数据格式

实现这样一颗树,需要设计三个类:树类(MultipleTree.java)、节点类(Node.java)、孩子列表类(Children.java);为了方便演示,还需要构造一些假的层次数据,因此还需要建一个构造假数据的类(VirtualDataGenerator.java),以下代码拷贝出来之后可直接运行测试:

 

package test;

 

import java.util.ArrayList;

import java.util.Comparator;

import java.util.HashMap;

import java.util.Iterator;

import java.util.List;

import java.util.Map;

import java.util.Set;

import java.util.Collections;

 

 

public class MultipleTree {

public static void main(String[] args) {

// 读取层次数据结果集列表 

List dataList VirtualDataGenerator.getVirtualResult();

 

// 节点列表(散列表,用于临时存储节点对象)

HashMap nodeList new HashMap();

// 根节点

Node root null;

// 根据结果集构造节点列表(存入散列表)

for (Iterator it dataList.iterator(); it.hasNext();) {

Map dataRecord (Map) it.next();

Node node new Node();

node.id (String) dataRecord.get("id");

node.text (String) dataRecord.get("text");

node.parentId (String) dataRecord.get("parentId");

nodeList.put(node.id, node);

}

// 构造无序的多叉树

Set entrySet nodeList.entrySet();

for (Iterator it entrySet.iterator(); it.hasNext();) {

Node node (Node) ((Map.Entry) it.next()).getValue();

if (node.parentId == null || node.parentId.equals("")) {

root node;

else {

((Node) nodeList.get(node.parentId)).addChild(node);

}

}

// 输出无序的树形菜单的JSON字符串

System.out.println(root.toString());

// 对多叉树进行横向排序

root.sortChildren();

// 输出有序的树形菜单的JSON字符串

System.out.println(root.toString());

 

// 程序输出结果如下(无序的树形菜单)(格式化后的结果):  

// {

// id '100000', 

// text '廊坊银行总行', 

// children [

// {

// id '110000', 

// text '廊坊分行', 

// children [

// {

// id '113000', 

// text '廊坊银行开发区支行', 

// leaf true

// },

// {

// id '111000', 

// text '廊坊银行金光道支行', 

// leaf true

// },

// {

// id '112000', 

// text '廊坊银行解放道支行', 

// children [

// {

// id '112200', 

// text '廊坊银行三大街支行', 

// leaf true

// },

// {

// id '112100', 

// text '廊坊银行广阳道支行', 

// leaf true

// }

// ]

// }

// ]

// }

// ]

// }

 

// 程序输出结果如下(有序的树形菜单)(格式化后的结果):

// {

// id '100000', 

// text '廊坊银行总行', 

// children [

// {

// id '110000', 

// text '廊坊分行', 

// children [

// {

// id '111000', 

// text '廊坊银行金光道支行', 

// leaf true

// },

// {

// id '112000', 

// text '廊坊银行解放道支行', 

// children [

// {

// id '112100', 

// text '廊坊银行广阳道支行', 

// leaf true

// },

// {

// id '112200', 

// text '廊坊银行三大街支行', 

// leaf true

// }

// ]

// },

// {

// id '113000', 

// text '廊坊银行开发区支行', 

// leaf true

// }

// ]

// }

// ]

// }

 

}

 

}

 

 

 

class Node {

 

public String id;

 

public String text;

 

public String parentId;

 

private Children children new Children();

 

// 先序遍历,拼接JSON字符串

public String toString() {

String result "{"

"id '" id "'"

", text '" text "'";

 

if (children != null && children.getSize() != 0) {

result += ", children children.toString();

else {

result += ", leaf true";

}

 

return result "}";

}

 

// 兄弟节点横向排序

public void sortChildren() {

if (children != null && children.getSize() != 0) {

children.sortChildren();

}

}

 

// 添加孩子节点

public void addChild(Node node) {

this.children.addChild(node);

}

}

 

 

class Children {

private List list new ArrayList();

 

public int getSize() {

return list.size();

}

 

public void addChild(Node node) {

list.add(node);

}

 

// 拼接孩子节点的JSON字符串

public String toString() {

String result "[";

for (Iterator it list.iterator(); it.hasNext();) {

result += ((Node) it.next()).toString();

result += ",";

}

result result.substring(0, result.length() 1);

result += "]";

return result;

}

 

// 孩子节点排序

public void sortChildren() {

// 对本层节点进行排序

// 可根据不同的排序属性,传入不同的比较器,这里传入ID比较器

Collections.sort(list, new NodeIDComparator());

// 对每个节点的下一层节点进行排序

for (Iterator it list.iterator(); it.hasNext();) {

((Node) it.next()).sortChildren();

}

}

}

 

 

class NodeIDComparator implements Comparator {

// 按照节点编号比较

public int compare(Object o1, Object o2) {

int j1 Integer.parseInt(((Node)o1).id);

    int j2 Integer.parseInt(((Node)o2).id);

    return (j1 j2 -1 (j1 == j2 1));

}

}

 

 

class VirtualDataGenerator {

// 构造无序的结果集列表,实际应用中,该数据应该从数据库中查询获得;

public static List getVirtualResult() {

List dataList new ArrayList();

 

HashMap dataRecord1 new HashMap();

dataRecord1.put("id", "112000");

dataRecord1.put("text", "廊坊银行解放道支行");

dataRecord1.put("parentId", "110000");

 

HashMap dataRecord2 new HashMap();

dataRecord2.put("id", "112200");

dataRecord2.put("text", "廊坊银行三大街支行");

dataRecord2.put("parentId", "112000");

 

HashMap dataRecord3 new HashMap();

dataRecord3.put("id", "112100");

dataRecord3.put("text", "廊坊银行广阳道支行");

dataRecord3.put("parentId", "112000");

 

HashMap dataRecord4 new HashMap();

dataRecord4.put("id", "113000");

dataRecord4.put("text", "廊坊银行开发区支行");

dataRecord4.put("parentId", "110000");

 

HashMap dataRecord5 new HashMap();

dataRecord5.put("id", "100000");

dataRecord5.put("text", "廊坊银行总行");

dataRecord5.put("parentId", "");

 

HashMap dataRecord6 new HashMap();

dataRecord6.put("id", "110000");

dataRecord6.put("text", "廊坊分行");

dataRecord6.put("parentId", "100000");

 

HashMap dataRecord7 new HashMap();

dataRecord7.put("id", "111000");

dataRecord7.put("text", "廊坊银行金光道支行");

dataRecord7.put("parentId", "110000");

 

dataList.add(dataRecord1);

dataList.add(dataRecord2);

dataList.add(dataRecord3);

dataList.add(dataRecord4);

dataList.add(dataRecord5);

dataList.add(dataRecord6);

dataList.add(dataRecord7);

 

return dataList;

  }

}

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有