0. 用法
TreeNode[] sillyTree = { new TreeNode("Root 1", new TreeNode[] { new TreeNode("Child 1", new TreeNode[] { new TreeNode("Gand Child 1", new TreeNode[] { }), new TreeNode("Gand Child 2", new TreeNode[] { }), new TreeNode("Gand Child 3", new TreeNode[] { }), new TreeNode("Gand Child 4", new TreeNode[] { }), }), new TreeNode("Child 2", new TreeNode[] { new TreeNode("Something Else", new TreeNode[] { }), new TreeNode("More of the same", new TreeNode[] { }), }), new TreeNode("Child 3", new TreeNode[] { }), new TreeNode("Child 4", new TreeNode[] { }), }), new TreeNode("Root 2", new TreeNode[] { new TreeNode("Something Else", new TreeNode[] { }), new TreeNode("More of the same", new TreeNode[] { }), }), new TreeNode("Root 3", new TreeNode[] { new TreeNode("Something Else", new TreeNode[] { }), new TreeNode("More of the same", new TreeNode[] { }), }), new TreeNode("Root 4", new TreeNode[] { }), }; TreeModel tm = new TreeModel(sillyTree); TreeComponent tree = new TreeComponent(tm); panel = new Container(new BorderLayout()); panel.addComponent(BorderLayout.CENTER, tree);
1. model
import java.util.Vector; /** * Arranges tree node objects, a node can essentially be anything * * @author Shai Almog */ public class TreeModel { Node root = null; public TreeModel(Node[] nodes) { root = new Node("root",nodes); } public Vector getChildren(Node parent) { if (parent==null) { parent = root; } Vector vec = new Vector(); Node[] children = parent.getChildren(); for (int i = 0; i < children.length; i++) { vec.addElement(children[i]); } return vec; } /** * Is the node a leaf or a folder */ public boolean isLeaf(Node node) { return (node.getChildren()==null || node.getChildren().length==0); } } class Node { Node[] children; String value; public Node(String value, Node[] children) { this.children = children; this.value = value; } public String toString() { return value; } public Node[] getChildren() { return children; } public void setChildren(Node[] children) { this.children = children; } }
2. component
import java.io.IOException; import java.util.Vector; import com.sun.lwuit.Button; import com.sun.lwuit.Component; import com.sun.lwuit.Container; import com.sun.lwuit.Image; import com.sun.lwuit.Label; import com.sun.lwuit.animations.CommonTransitions; import com.sun.lwuit.events.ActionEvent; import com.sun.lwuit.events.ActionListener; import com.sun.lwuit.layouts.BorderLayout; import com.sun.lwuit.layouts.BoxLayout; import com.sun.lwuit.plaf.Style; /** * tree组件,改进了节点收缩方法,节点排列间距以及展开收缩时对节点间距的影响 * * @Author guo * @EditTime 2009-5-3 下午04:42:48 */ public class TreeComponent extends Container { private static final String KEY_OBJECT = "TREE_OBJECT"; private static final String KEY_PARENT = "TREE_PARENT"; private static final String KEY_EXPANDED = "TREE_NODE_EXPANDED"; private static final String KEY_DEPTH = "TREE_DEPTH"; private ActionListener expansionListener = new ActionListener() { public void actionPerformed(ActionEvent evt) { Component c = (Component)evt.getSource(); Object e = c.getClientProperty(KEY_EXPANDED); if(e != null && e.equals("true")) { collapseNode(c); ((Button)c).setIcon(folder); } else { expandNode(c); ((Button)c).setIcon(folderopen); } } }; private TreeModel model; private Image folder; private Image folderopen; private Image nodeImage; private int depthIndent = 15; public TreeComponent(TreeModel model) { try { this.model = model; folder = Image.createImage("/folder.gif"); folderopen = Image.createImage("/folderopen.gif"); //nodeImage = Image.createImage("/page.png"); setLayout(new BoxLayout(BoxLayout.Y_AXIS)); buildBranch(null, 0, this); setScrollableY(true); } catch (Exception ex) { ex.printStackTrace(); } } private void expandNode(Component c) { c.putClientProperty(KEY_EXPANDED, "true"); int depth = ((Integer)c.getClientProperty(KEY_DEPTH)).intValue(); Container parent = c.getParent(); Node o = (Node) c.getClientProperty(KEY_OBJECT); Container dest = new Container(new BoxLayout(BoxLayout.Y_AXIS)); Label dummy = new Label(); // sean Style s = dummy.getStyle(); s.setPadding(Button.TOP, 0); s.setPadding(Button.BOTTOM, 0); s.setMargin(Button.TOP, 0); s.setMargin(Button.BOTTOM, 0); parent.addComponent(BorderLayout.CENTER, dummy); buildBranch(o, depth, dest); parent.replace(dummy, dest, CommonTransitions.createEmpty()); } private void collapseNode(Component c) { c.putClientProperty(KEY_EXPANDED, null); Container p = c.getParent(); // sean start from 1 not 0 for(int iter = 1 ; iter < p.getComponentCount() ; iter++) { Label dummy = new Label(); // sean Style s = dummy.getStyle(); s.setPadding(Button.TOP, 0); s.setPadding(Button.BOTTOM, 0); s.setMargin(Button.TOP, 0); s.setMargin(Button.BOTTOM, 0); p.replace(p.getComponentAt(iter), dummy, CommonTransitions.createEmpty()); p.removeComponent(dummy); } } /** * Adds the child components of a tree branch to the given container.nt */ protected void buildBranch(Node parent, int depth, Container destination) { Vector children = model.getChildren(parent); int size = children.size(); Integer depthVal = new Integer(depth + 1); for(int iter = 0 ; iter < size ; iter++) { Node current = (Node) children.elementAt(iter); Button nodeComponent = createNodeComponent(current, depth); if(model.isLeaf(current)) { Style s = nodeComponent.getStyle(); s.setPadding(Button.LEFT, s.getPadding(Button.LEFT)+4); destination.addComponent(nodeComponent); } else { Container componentArea = new Container(new BorderLayout()); componentArea.addComponent(BorderLayout.NORTH, nodeComponent); destination.addComponent(componentArea); nodeComponent.addActionListener(expansionListener); } nodeComponent.putClientProperty(KEY_OBJECT, current); nodeComponent.putClientProperty(KEY_PARENT, parent); nodeComponent.putClientProperty(KEY_DEPTH, depthVal); } } protected Button createNodeComponent(Node node, int depth) { Button cmp = new Button(node.toString()); if(model.isLeaf(node)) { cmp.setIcon(nodeImage); } else { cmp.setIcon(folder); } updateNodeComponentStyle(cmp.getStyle(), depth); return cmp; } protected void updateNodeComponentStyle(Style s, int depth) { s.setBorder(null); // sean s.setPadding(Button.TOP, 0); s.setPadding(Button.BOTTOM, 0); s.setMargin(Button.TOP, 0); s.setMargin(Button.BOTTOM, 0); s.setPadding(LEFT, depth * depthIndent); } }