0.引子
通常一个TreeNode (DefaultMutableTreeNode)如果没有子结点,它的节点显示为不可展开的节点,有时候我们希望即使该节点暂时没有装载子结点仍然显示为可展开的节点(如图 )。比如,当加载子结点比较耗时或者需要动态刷新,可以延时加载子结点,即在展开节点的时候再去装载子结点。
1.由来及解决方案
该属性取决于,DefaultTreeModel的isLeaf方法
通常一个TreeNode (DefaultMutableTreeNode)如果没有子结点,它的节点显示为不可展开的节点,有时候我们希望即使该节点暂时没有装载子结点仍然显示为可展开的节点(如图 )。比如,当加载子结点比较耗时或者需要动态刷新,可以延时加载子结点,即在展开节点的时候再去装载子结点。
1.由来及解决方案
该属性取决于,DefaultTreeModel的isLeaf方法
/** * Returns whether the specified node is a leaf node. * The way the test is performed depends on the * <code>askAllowsChildren</code> setting. * * @param node the node to check * @return true if the node is a leaf node * * @see #asksAllowsChildren * @see TreeModel#isLeaf */ publicboolean isLeaf(Object node) { if(asksAllowsChildren) return !((TreeNode)node).getAllowsChildren(); return ((TreeNode)node).isLeaf(); }而asksAllowsChildren由方法setAsksAllowsChildren设定
/** * Sets whether or not to test leafness by asking getAllowsChildren() * or isLeaf() to the TreeNodes. If newvalue is true, getAllowsChildren() * is messaged, otherwise isLeaf() is messaged. */ publicvoid setAsksAllowsChildren(boolean newValue) { asksAllowsChildren = newValue; }注意,在setRoot时可以只设定一次
model.setRoot(root); /* * Since nodes are added dynamically in this application, the only true * leaf nodes are nodes that don't allow children to be added. (By * default, askAllowsChildren is false and all nodes without children * are considered to be leaves.) * * But there's a complication: when the tree structure changes, JTree * pre-expands the root node unless it's a leaf. To avoid having the * root pre-expanded, we set askAllowsChildren *after* assigning the * new root. */ model.setAsksAllowsChildren(true);
而在调用model.nodeStructureChanged(node)前后要分别设置为false和true。这是因为nodeStructureChanged会自动的试图展开节点node,如果isLeaf返回为false。试想,asksAllowsChildren返回true,则一个结点即使没有子结点,只要设置了allowsChildren,对应的treeNodeModel的isLeaf就会返回true。然而当自动展开节点的时候发现并没有子结点,当然就会把图标去掉了。而先把asksAllowsChildren设为false,就不会去试图展开该节点,然后设为true,该节点就会显示为。
/** * Determines whether or not this node is allowed to have children. * If <code>allows</code> is false, all of this node's children are * removed. * <p> * Note: By default, a node allows children. * * @param allows true if this node is allowed to have children */ publicvoid setAllowsChildren(boolean allows) { if (allows != allowsChildren) { allowsChildren = allows; if (!allowsChildren) { removeAllChildren(); } } }
node.removeAllChildren(); DefaultTreeModel model = (DefaultTreeModel) cardTreeView.getModel(); /* * To avoid having JTree re-expand the root node, we disable * ask-allows-children when we notify JTree about the new node * structure. */ model.setAsksAllowsChildren(false); model.nodeStructureChanged(node); model.setAsksAllowsChildren(true);