TreeStructureChanged vs treeNodesChanged

Hi all,
I'm working with tree models to show to the user a tree data structure. The idea is simple: I've got a few Person objects, each person has a few properties (in this example the name and the surname) and a list of Skill objects, each with a couple of properties. I want to show the data in a tree using a model.
I worked on the thread http://forum.java.sun.com/thread.jspa?threadID=5242097 and found that I had to inform the tree about changes. This rises a new problem (the one of this question): I found that only if I call listener.treeStructureChanged(event); I can see the node changing, but a treeNodesChanged instead should be more appropriate, since it does not forces loading the whole tree. Anybody can help me understanding why a call to treeNodesChanged does not work?
import java.awt.Component;
import java.util.*;
import javax.swing.*;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.*;
class Person{
    String name = null;
    String surname = null;
    int id = 0;
    private List<Skill> skills = new LinkedList<Skill>();
    private static int counter = 1;
    Person(String name, String surname){
     this.name = name;
     this.surname = surname;
     id = counter++;
    public String getName() {
        return name;
    public void setName(String name) {
        this.name = name;
    public String getSurname() {
        return surname;
    public void setSurname(String surname) {
        this.surname = surname;
    public String toString(){
     return "Person number " + id;
    public void addSkill(Skill skill){
     this.skills.add(skill);
    public List<Skill> getSkills(){
     return this.skills;
    public void removeSkill(Skill sk){
     this.skills.remove(sk);
class Skill{
    private int skillId = 0;
    private String skillDescription = null;
    public Skill(int id, String description){
     super();
     this.skillId = id;
     this.skillDescription = description;
    public String toString(){
     return "Skill number " + this.skillId + " {" + this.skillDescription + "}";
     * Returns the value of the field <code>skillDescription</code>.
     * @return the skillDescription
    public String getSkillDescription() {
        return skillDescription;
     * Allows the set-up of the field <code>skillDescription</code> to the specified value.
     * @param skillDescription the <code>skillDescription</code> value to set
    public void setSkillDescription(String skillDescription) {
        this.skillDescription = skillDescription;
     * Returns the value of the field <code>skillId</code>.
     * @return the skillId
    public int getSkillId() {
        return skillId;
     * Allows the set-up of the field <code>skillId</code> to the specified value.
     * @param skillId the <code>skillId</code> value to set
    public void setSkillId(int skillId) {
        this.skillId = skillId;
class PersonModel implements TreeModel{
     private List<Person> people = null;
     private String root = "## HERE THE ROOT ##";
     private LinkedList<TreeModelListener> listeners = new LinkedList<TreeModelListener>();
     public PersonModel(List<Person> people){
          super();
          this.people = people;
     @Override
     public void addTreeModelListener(TreeModelListener l) {
          this.listeners.add(l);
     @Override
     public Object getChild(Object parent, int index) {
          System.out.println("getChild called with " + parent + " - " + index);
          Object ret = null;
          if( parent instanceof Person ){
               Person parentPerson = (Person) parent;
               // index = 1 => name
               switch(index){
               case 0:     ret = parentPerson.getName(); break;
               case 1: ret = parentPerson.getSurname(); break;
               default: ret = parentPerson.getSkills().get(index - 2); break;
               System.out.println("\n\treturning " + ret);
               return ret;
          else
          if( parent instanceof Skill ){
               Skill parentSkill = (Skill) parent;
               switch(index){
               case 0: ret = parentSkill.getSkillId(); break;
               case 1: ret = parentSkill.getSkillDescription(); break;
               default: ret = "SKILL WHAT?"; break;
               System.out.println("\n\t returning " + ret);
               return ret;
          else
          if( parent.equals(root)){
               ret = this.people.get(index);
               System.out.println("\n\t returning " + ret);
               return ret;
          else
               return "NOT FOUND IN THE MODEL";
     @Override
     public int getChildCount(Object parent) {
          System.out.println("getChildCount called " + parent);
          if( parent instanceof Person )
               return 2 + ((Person)parent).getSkills().size();
          else
          if( parent instanceof Skill )
               return 2;
          else
          if( parent.equals(root))
               return this.people.size();
          else
               return -1;
     @Override
     public int getIndexOfChild(Object parent, Object child) {
          System.out.println("getIndexOfChild called " + parent + " - " + child);
          if( parent instanceof Person ){
               Person parentPerson = (Person) parent;
               if( child instanceof Skill )
                    return parentPerson.getSkills().indexOf(child);
               else
               if( child instanceof String ){
                    String childString = (String) child;
                    if( childString.equals( parentPerson.getName() )){
                         System.out.println("\n\tfound child at index 1");
                         return 1;
                    else{
                         System.out.println("\n\t found child at index 2");
                         return 2;
          else
          if( parent instanceof Skill ){
               Skill parentSkill = (Skill) parent;
               String childString = (String) child;
               if( childString.equals( parentSkill.getSkillId())){
                    System.out.println("\n\tfound child at index 1");
                    return 1;
               else{
                    System.out.println("\n\tfound child at index 2");
                    return 2;
          else
          if( parent.equals( this.root )){
               System.out.println("\n\treturning person " + this.people.indexOf(child));
               return this.people.indexOf(child);
               return -1;
     @Override
     public Object getRoot() {
          return this.root;
     @Override
     public boolean isLeaf(Object node) {
          System.out.println("isLeaf called " + node);
          if( node instanceof String && node.equals(this.root) == false){
               System.out.println("\n\tthis is a leaf");
               return true;
          else{
               System.out.println("\n\tthis is not a leaf");
               return false;
     @Override
     public void removeTreeModelListener(TreeModelListener l) {
          // TODO Auto-generated method stub
     @Override
     public void valueForPathChanged(TreePath path, Object newValue) {
          // TODO Auto-generated method stub
     protected void fireTreeStructureChanged(Person p){
          TreeModelEvent event = new TreeModelEvent(this, new Object[]{ this.getRoot(), p});
          for(TreeModelListener listener : this.listeners){
               System.out.println("Notifico evento di ristrutturazione a " + listener);
               listener.treeStructureChanged(event);
public class PersonTreeTest extends JFrame {
     private JTree tree = null;
     private TreeModel model = null;
     public PersonTreeTest(List<Person> people){
          super("Tree Test");
          this.model = new PersonModel(people);
          this.tree = new JTree(model);
          this.add(new JScrollPane(this.tree) );
          this.setSize(300,300);
          this.setVisible(true);
     public static void main(String argv[]) throws Exception{
          List<Person> people = new LinkedList<Person>();
          for(int i=0;i<10000;i++){
               Person p = new Person("PERSON" + i,"---");
               people.add(p);
          Person p1 = new Person("Luca", "Ferrari");
          Skill s1 = new Skill(1,"A FIRST SKILL");
          Skill s2 = new Skill(2, "A SECOND SKILL");
          Skill s3 = new Skill(3, "A THIRD SKILL");
          p1.addSkill(s1);
          p1.addSkill(s2);
          Person p2 = new Person("Sam","Ferrari");
          p2.addSkill(s3);
          people.add(p1);
          people.add(p2);
          PersonTreeTest test = new PersonTreeTest(people);
          Thread.currentThread().sleep(5000);
          System.out.println("Changing a node");
          p1.setName("LLUUCCAA");
          PersonModel model = (PersonModel) test.tree.getModel();
          model.fireTreeStructureChanged(p1);
}

Hi,
I've tried also to notify the tree of a node changes specifying the root node (and no one child path), but it still does not work:
protected void fireTreeStructureChanged(Person p){
                TreeModelEvent event = new TreeModelEvent(this, new Object[]{ this.getRoot()});
                for(TreeModelListener listener : this.listeners){
                        listener.treeNodesChanged(event);
        }The javadoc for the treeNodesChanged says that: The node(s) have not changed locations in the tree or altered their children arrays, but other attributes have changed and may affect presentation. Example: the name of a file has changed, but it is in the same location in the file system.
So it should be correct, in my example, to call the treeNodesChanged, but it is not working. Any idea?
Thanks,
Luca

Similar Messages

  • JTree collapses when using treeStructureChanged

    I'm using a JTree with the default model and L&F (basic). When I call treeStructureChanged, it collapses the entire tree even if I specify the TreePath of the change.
    Any ideas what i'm doing wrong?
    Thanks,
    Assaf.

    Thanks for replying. I think this may just be a flaw in the default implementation, because it does look like it can support it. Just wanted to know if there was an easy way before I go and mangle Sun's code.

  • TreeNodesChanged only called when root changes

    Hi all, just a quick one,
    I have a JTree and TreeModel setup, and set up a tree model listener as follows:
    public void treeNodesChanged(TreeModelEvent treeModelEvent) {
            // The user has changed the name of a node
            System.out.println("TREENODES CHANGED");
    }But this only gets called when the root node is changed. When the other (leaf) nodes are changed (by changed, i mean double-clicking the node and changing the title of it in the tree GUI) everything goes through ok (my model is changed properly with setUserObject ), but treeNodesChanged doesn't get called... :-S
    Any hints?

    Post a small demo code that is generally compilable, runnable and could reproduce your problem. See: http://homepage1.nifty.com/algafield/sscce.html and/or
    http://riters.com/JINX/index.cgi/Suggestions_20for_20Asking_20Questions_20on_20Newsgroups

  • Useful Code of the Day:  Hideable Tree Nodes

    Someone posted about how they could selectively hide tree nodes, and I already had this AbstractTreeModel class (which does some things DefaultTreeModel does and some it doesn't) and a concrete subclass for TreeNode objects, so I was thinking how one could do hideable nodes. So I came up with this solution.
    There's 4 classes here:
    - AbstractTreeModel is the base for the concrete TreeNodeTreeModel
    - TreeNodeTreeModel extends AbstractTreeModel to support TreeNodes (DefautlMutableTreeNode, etc.)
    - HideableMutableTreeNode which is a DefautlMutableTreeNode subclass which has a visible field (with is/set methods, of course).
    - HideableTreeModel is the hideable model which is a subclass of TreeNodeTreeModel.
    A HideableMutableTreeNode can be set invisible directly, but the tree still needs to be notified to update. So it's best to use the methods in HideableTreeModel which set a node's visibility which notify the tree of changes accordingly. Methods are also provided to check a full path's visibility or ensure a node including all parent nodes are visible.
    A HideableTreeModel can take any TreeNode class, it doesn't have to be all HideableMutableTreeNodes, but only HideableMutableTreeNodes can be made invisible, of course. Any other TreeNode type would just be considered visible.
    Hiding nodes works basically by making the tree think there's less nodes then there are. And to do this, the node counts and child index search just works by looping thru the parent's children. This has potential perfomance drawbacks of course, since one has to loop thru the node's children to get nodes every time. This could be alleviated by not supporting non-hideable nodes changing the internal maintenance of HideableMutableTreeNode contents. But I'll leave that to whoever really needs it. It shouldn't be a problem if there are are a relatively small set of child nodes in any given parent.
    Also, note that the root node in the model cannot be made invisible, cuz it'd be redundant since JTree can be set to hide the root node.
    // *** HideableTreeModel ***
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.event.*;
    import javax.swing.tree.*;
    * <code>HideableTreeModel</code> is an <code>TreeNodeTreeModel</code>
    * implementation for <code>HideableMutableTreeNode</code> objects.  The
    * model can also take any other <code>javax.swing.tree.TreeNode</code>
    * objects. 
    public class HideableTreeModel extends TreeNodeTreeModel {
          * Creates a new <code>HideableTreeModel</code> object.
          * @param  root  the root node
         public HideableTreeModel(TreeNode root) {
              super(root);
          * Checks if the specified node is visible.  A node can only be
          * hidden if the node is an instance of <code>HideableMutableTreeNode</code>.  <br />
          * <br />
          * Note that this only test the visibility of the specified node, not
          * whether a parent node is visible.  Use <code>isPathToNodeVisible(Object)</code>
          * to check if the full path is visible. 
          * @param  node  the node
          * @param  true if the node is visible, else false
         public boolean isNodeVisible(Object node) {
              if(node != getRoot()) {
                   if(node instanceof HideableMutableTreeNode) {
                        return ((HideableMutableTreeNode)node).isVisible();
              return true;
          * Sets the specified node to be hidden.  A node can only be made hidden
          * if the node is an instance of <code>HideableMutableTreeNode</code>.  <br />
          * <br />
          * Note that this method will notify the tree to reflect any changes to
          * node visibility.  <br />
          * <br />
          * Note that this will not alter the visibility of any nodes in the
          * specified node's path to the root node.  Use
          * <code>ensurePathToNodeVisible(Object)</code> instead to make sure the
          * full path down to that node is visible.  <br />
          * <br />
          * Note that this method will notify the tree to reflect any changes to
          * node visibility. 
          * @param  node  the node
          * @param  v     true for visible, false for hidden
          * @param  true if the node's visibility could actually change, else false
         public boolean setNodeVisible(Object node, boolean v) {
              // can't hide root
              if(node != getRoot()) {
                   if(node instanceof HideableMutableTreeNode) {
                        HideableMutableTreeNode n = (HideableMutableTreeNode)node;
                        // don't fix what ain't broke...
                        if(v != n.isVisible()) {
                             TreeNode parent = n.getParent();
                             if(v) {
                                  // need to get index after showing...
                                  n.setVisible(v);
                                  int index = getIndexOfChild(parent, n);
                                  super.nodeInserted(parent, n, index);
                             } else {
                                  // need to get index before hiding...
                                  int index = getIndexOfChild(parent, n);
                                  n.setVisible(v);
                                  super.nodeRemoved(parent, n, index);
                        return true;
              return false;
          * Checks if the specified node is visible and all nodes above it are
          * visible. 
          * @param  node  the node
          * @param  true if the path is visible, else false
         public boolean isPathToNodeVisible(Object node) {
              Object[] path = getPathToRoot(node);
              for(int i = 0; i < path.length; i++) {
                   if(!isNodeVisible(path)) {
                        return false;
              return true;
         * Sets the specified node and all nodes above it to be visible.
         * Note that this method will notify the tree to reflect any changes to
         * node visibility.
         * @param node the node
         public void ensurePathToNodeVisible(Object node) {
              Object[] path = getPathToRoot(node);
              for(int i = 0; i < path.length; i++) {
                   setNodeVisible(path[i], true);
         * Returns the child of parent at index index in the parent's child array.
         * @param parent the parent node
         * @param index the index
         * @return the child or null if no children
         public Object getChild(Object parent, int index) {
              if(parent instanceof TreeNode) {
                   TreeNode p = (TreeNode)parent;
                   for(int i = 0, j = -1; i < p.getChildCount(); i++) {
                        TreeNode pc = (TreeNode)p.getChildAt(i);
                        if(isNodeVisible(pc)) {
                             j++;
                        if(j == index) {
                             return pc;
              return null;
         * Returns the number of children of parent.
         * @param parent the parent node
         * @return the child count
         public int getChildCount(Object parent) {
              int count = 0;
              if(parent instanceof TreeNode) {
                   TreeNode p = (TreeNode)parent;
                   for(int i = 0; i < p.getChildCount(); i++) {
                        TreeNode pc = (TreeNode)p.getChildAt(i);
                        if(isNodeVisible(pc)) {
                             count++;
              return count;
         * Returns the index of child in parent.
         * @param parent the parent node
         * @param child the child node
         * @return the index of the child node in the parent
         public int getIndexOfChild(Object parent, Object child) {
              int index = -1;
              if(parent instanceof TreeNode && child instanceof TreeNode) {
                   TreeNode p = (TreeNode)parent;
                   TreeNode c = (TreeNode)child;
                   if(isNodeVisible(c)) {
                        index = 0;
                        for(int i = 0; i < p.getChildCount(); i++) {
                             TreeNode pc = (TreeNode)p.getChildAt(i);
                             if(pc.equals(c)) {
                                  return index;
                             if(isNodeVisible(pc)) {
                                  index++;
              return index;
         * Main method for testing.
         * @param args the command-line arguments
         public static void main(String[] args) {
              JFrame f = new JFrame();
              f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              HideableMutableTreeNode root = new HideableMutableTreeNode("root");
              root.add(new HideableMutableTreeNode("child_1"));
              final HideableMutableTreeNode c2 = new HideableMutableTreeNode("child_2");
              c2.setVisible(false);
              final HideableMutableTreeNode c2a = new HideableMutableTreeNode("child_2_A");
              c2.add(c2a);
              c2.add(new HideableMutableTreeNode("child_2_B"));
              root.add(c2);
              HideableMutableTreeNode c3 = new HideableMutableTreeNode("child_3");
              HideableMutableTreeNode cC = new HideableMutableTreeNode("child_3_C");
              cC.setVisible(false);
              c3.add(cC);
              c3.add(new HideableMutableTreeNode("child_3_D"));
              root.add(c3);
              root.add(new HideableMutableTreeNode("child_4"));
              root.add(new HideableMutableTreeNode("child_5"));
              DefaultMutableTreeNode c6 = new DefaultMutableTreeNode("child_6");
              c6.add(new DefaultMutableTreeNode("child_6_A"));
              c6.add(new DefaultMutableTreeNode("child_6_B"));
              root.add(c6);
              final HideableTreeModel model = new HideableTreeModel(root);
              JTree tree = new JTree(model);
              f.getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER);
              JButton b = new JButton("toggle");
              b.addActionListener(new ActionListener() {
                   public void actionPerformed(ActionEvent e) {
                        model.setNodeVisible(c2, !model.isNodeVisible(c2));
                        //model.ensurePathToNodeVisible(c2a);
              f.getContentPane().add(b, BorderLayout.SOUTH);
              f.pack();
              f.setSize(300, 500);
              f.show();
    // *** HideableMutableTreeNode ***
    import javax.swing.*;
    import javax.swing.tree.*;
    * <code>HideableMutableTreeNode</code> is a <code>DefaultMutableTreeNode</code>
    * implementation that works with <code>HideableTreeModel</code>.
    public class HideableMutableTreeNode extends DefaultMutableTreeNode {
         * The node is visible flag.
         public boolean visible = true;
         * Creates a tree node that has no parent and no children, but which
         * allows children.
         public HideableMutableTreeNode() {
              super();
         * Creates a tree node with no parent, no children, but which allows
         * children, and initializes it with the specified user object.
         * @param userObject - an Object provided by the user that
         * constitutes the node's data
         public HideableMutableTreeNode(Object userObject) {
              super(userObject);
         * Creates a tree node with no parent, no children, initialized with the
         * specified user object, and that allows children only if specified.
         * @param userObject - an Object provided by the user that
         * constitutes the node's data
         * @param allowsChildren - if true, the node is allowed to have child
         * nodes -- otherwise, it is always a leaf node
         public HideableMutableTreeNode(Object userObject, boolean allowsChildren) {
              super(userObject, allowsChildren);
         * Checks if the node is visible.
         * @return true if the node is visible, else false
         public boolean isVisible() {
              return this.visible;
         * Sets if the node is visible.
         * @param v true if the node is visible, else false
         public void setVisible(boolean v) {
              this.visible = v;
    // *** TreeNodeTreeModel ***
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.event.*;
    import javax.swing.tree.*;
    * <code>TreeNodeTreeModel</code> is an <code>AbstractTreeModel</code>
    * implementation for <code>javax.swing.tree.TreeNode</code> objects.
    public class TreeNodeTreeModel extends AbstractTreeModel {
         * Creates a new <code>TreeNodeTreeModel</code> object.
         * @param root the root node
         public TreeNodeTreeModel(TreeNode root) {
              super();
              setRoot(root);
         * Returns the parent of the child node.
         * @param node the child node
         * @return the parent or null if root
         public Object getParent(Object node) {
              if(node != getRoot() && (node instanceof TreeNode)) {
                   return ((TreeNode)node).getParent();
              return null;
         * Returns the child of parent at index index in the parent's child array.
         * @param parent the parent node
         * @param index the index
         * @return the child or null if no children
         public Object getChild(Object parent, int index) {
              if(parent instanceof TreeNode) {
                   return ((TreeNode)parent).getChildAt(index);
              return null;
         * Returns the number of children of parent.
         * @param parent the parent node
         * @return the child count
         public int getChildCount(Object parent) {
              if(parent instanceof TreeNode) {
                   return ((TreeNode)parent).getChildCount();
              return 0;
         * Returns the index of child in parent.
         * @param parent the parent node
         * @param child the child node
         * @return the index of the child node in the parent
         public int getIndexOfChild(Object parent, Object child) {
              if(parent instanceof TreeNode && child instanceof TreeNode) {
                   return ((TreeNode)parent).getIndex((TreeNode)child);
              return -1;
         * Returns true if node is a leaf.
         * @param node the node
         * @return true if the node is a leaf
         public boolean isLeaf(Object node) {
              if(node instanceof TreeNode) {
                   return ((TreeNode)node).isLeaf();
              return true;
         * Main method for testing.
         * @param args the command-line arguments
         public static void main(String[] args) {
              JFrame f = new JFrame();
              f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
              root.add(new DefaultMutableTreeNode("child_1"));
              DefaultMutableTreeNode c2 = new DefaultMutableTreeNode("child_2");
              c2.add(new DefaultMutableTreeNode("child_2_A"));
              c2.add(new DefaultMutableTreeNode("child_2_B"));
              root.add(c2);
              root.add(new DefaultMutableTreeNode("child_3"));
              root.add(new DefaultMutableTreeNode("child_4"));
              JTree tree = new JTree(new TreeNodeTreeModel(root));
              f.getContentPane().add(new JScrollPane(tree));
              f.pack();
              f.setSize(300, 500);
              f.show();
    // *** AbstractTreeModel ***
    import java.awt.*;
    import java.awt.event.*;
    import java.io.*;
    import java.net.*;
    import java.text.*;
    import java.util.*;
    import javax.swing.*;
    import javax.swing.event.*;
    import javax.swing.tree.*;
    public abstract class AbstractTreeModel implements TreeModel {
         * The list of tree model listeners.
         private Vector modelListeners = new Vector();
         * The root object of the tree.
         private Object root = null;
         * Basic no-op constructor.
         public AbstractTreeModel() {
         * Gets the root object of the tree.
         * @return the root object
         public Object getRoot() {
              return this.root;
         * Sets the root object of the tree.
         * @param r the root object
         protected void setRoot(Object r) {
              this.root = r;
         * Gets the path to the root node for the specified object.
         * @param node the root node
         * @return the path to the object or <CODE>null</CODE>
         public Object[] getPathToRoot(Object node) {
              return getPathToRoot(node, 0);
         * Gets the path to the root node for the specified object.
         * @param node the root node
         * @param i the current index
         * @return the path to the object or <CODE>null</CODE>
         private Object[] getPathToRoot(Object node, int i) {
              Object anode[];
              if(node == null) {
                   if(i == 0) {
                        return null;
                   anode = new Object[i];
              } else {
                   i++;
                   if(node == getRoot()) {
                        anode = new Object[i];
                   } else {
                        anode = getPathToRoot(getParent(node), i);
                   anode[anode.length - i] = node;
              return anode;
         * Gets the parent object of the specified object. This method is not
         * part of the <code>javax.swing.tree.TreeModel</code> interface, but is
         * required to support the <code>getPathToRoot(Object)</code> method,
         * which is widely used in this class. Therefore, it is important to
         * correctly implement this method.
         * @param obj the object
         * @parma the parent object or null if no parent or invalid object
         protected abstract Object getParent(Object obj);
         * Adds a listener for the <CODE>TreeModelEvent</CODE> posted after the
         * tree changes.
         * @param l the tree model listener
         public void addTreeModelListener(TreeModelListener l) {
              modelListeners.addElement(l);
         * Removes a listener previously added with addTreeModelListener().
         * @param l the tree model listener
         public void removeTreeModelListener(TreeModelListener l) {
              modelListeners.removeElement(l);
         * Forces the tree to reload. This is useful when many changes occur
         * under the root node in the tree structure.
         * <b>NOTE:</b> This will cause the tree to be collapsed. To maintain
         * the expanded nodes, see the <code>getExpandedPaths(JTree)</code>
         * and <code>expandPaths(JTree, ArrayList)</code> methods.
         * @see #getExpandedPaths(JTree)
         * @see #expandPaths(JTree, ArrayList)
         public void reload() {
              reload(getRoot());
         * Forces the tree to repaint. This is useful when many changes occur
         * under a specific node in the tree structure.
         * <b>NOTE:</b> This will cause the tree to be collapsed below the
         * updated node.
         * @param node the node that changed
         public void reload(Object node) {
              if(node != null) {
                   TreePath tp = new TreePath(getPathToRoot(node));
                   fireTreeStructureChanged(new TreeModelEvent(this, tp));
         * Messaged when the user has altered the value for the item identified
         * by <CODE>path</CODE> to <CODE>newValue</CODE>.
         * @param path the path to the changed object
         * @param newValue the new value
         public void valueForPathChanged(TreePath path, Object newValue) {
              nodeChanged(path.getLastPathComponent());
         * Notifies the tree that nodes were inserted. The index is looked up
         * automatically.
         * @param node the parent node
         * @param child the inserted child node
         public void nodeInserted(Object node, Object child) {
              nodeInserted(node, child, -1);
         * Notifies the tree that nodes were inserted.
         * @param node the parent node
         * @param child the inserted child node
         * @param index the index of the child
         public void nodeInserted(Object node, Object child, int index) {
              if(index < 0) {
                   index = getIndexOfChild(node, child);
              if(node != null && child != null && index >= 0) {
                   TreePath tp = new TreePath(getPathToRoot(node));
                   int[] ai = { index };
                   Object[] ac = { child };
                   fireTreeNodesInserted(new TreeModelEvent(this, tp, ai, ac));
         * Notifies the tree that nodes were removed. The index is required
         * since by this point, the object will no longer be in the tree.
         * @param node the parent node
         * @param child the removed child node
         * @param index the index of the child
         public void nodeRemoved(Object node, Object child, int index) {
              if(node != null && child != null && index >= 0) {
                   TreePath tp = new TreePath(getPathToRoot(node));
                   int[] ai = { index };
                   Object[] ac = { child };
                   fireTreeNodesRemoved(new TreeModelEvent(this, tp, ai, ac));
         * Notifies the tree that a node was changed.
         * @param node the changed node
         public void nodeChanged(Object node) {
              if(node != null) {
                   TreePath tp = new TreePath(getPathToRoot(node));
                   fireTreeNodesChanged(new TreeModelEvent(this, tp, null, null));
         * Fires "tree nodes changed" events to all listeners.
         * @param event the tree model event
         protected void fireTreeNodesChanged(TreeModelEvent event) {
              for(int i = 0; i < modelListeners.size(); i++) {
                   ((TreeModelListener)modelListeners.elementAt(i)).treeNodesChanged(event);
         * Fires "tree nodes inserted" events to all listeners.
         * @param event the tree model event
         protected void fireTreeNodesInserted(TreeModelEvent event) {
              for(int i = 0; i < modelListeners.size(); i++) {
                   ((TreeModelListener)modelListeners.elementAt(i)).treeNodesInserted(event);
         * Fires "tree nodes removed" events to all listeners.
         * @param event the tree model event
         protected void fireTreeNodesRemoved(TreeModelEvent event) {
              for(int i = 0; i < modelListeners.size(); i++) {
                   ((TreeModelListener)modelListeners.elementAt(i)).treeNodesRemoved(event);
         * Fires "tree structure changed" events to all listeners.
         * @param event the tree model event
         protected void fireTreeStructureChanged(TreeModelEvent event) {
              for(int i = 0; i < modelListeners.size(); i++) {
                   ((TreeModelListener)modelListeners.elementAt(i)).treeStructureChanged(event);
         * Records the list of currently expanded paths in the specified tree.
         * This method is meant to be called before calling the
         * <code>reload()</code> methods to allow the tree to store the paths.
         * @param tree the tree
         * @param pathlist the list of expanded paths
         public ArrayList getExpandedPaths(JTree tree) {
              ArrayList expandedPaths = new ArrayList();
              addExpandedPaths(tree, tree.getPathForRow(0), expandedPaths);
              return expandedPaths;
         * Adds the expanded descendants of the specifed path in the specified
         * tree to the internal expanded list.
         * @param tree the tree
         * @param path the path
         * @param pathlist the list of expanded paths
         private void addExpandedPaths(JTree tree, TreePath path, ArrayList pathlist) {
              Enumeration enum = tree.getExpandedDescendants(path);
              while(enum.hasMoreElements()) {
                   TreePath tp = (TreePath)enum.nextElement();
                   pathlist.add(tp);
                   addExpandedPaths(tree, tp, pathlist);
         * Re-expands the expanded paths in the specified tree. This method is
         * meant to be called before calling the <code>reload()</code> methods
         * to allow the tree to store the paths.
         * @param tree the tree
         * @param pathlist the list of expanded paths
         public void expandPaths(JTree tree, ArrayList pathlist) {
              for(int i = 0; i < pathlist.size(); i++) {
                   tree.expandPath((TreePath)pathlist.get(i));

    Hey
    I'm not trying to show anyone up here, but having just built a tree model for displaying an XML document in a tree, I thought this seemed like a neat exercise.
    I implemented this very differently from the @OP. I only have one class, HiddenNodeTreeModel. All the hidden node data is stored in the model itself in my class. The advantage of what I've created is it will work with any TreeModel. The disadvantage is that I think it's not going to be very scalable - the additional computing to get the number of child nodes and to adjust indexes is heavy. So if you need a scalable solution definitely don't use this.
    Anyway here you go
    HiddenNodeTreeModel.java
    ======================
    package tjacobs.ui.tree;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Iterator;
    import javax.swing.JFrame;
    import javax.swing.JMenu;
    import javax.swing.JMenuBar;
    import javax.swing.JMenuItem;
    import javax.swing.JTree;
    import javax.swing.event.TreeModelListener;
    import javax.swing.tree.DefaultMutableTreeNode;
    import javax.swing.tree.DefaultTreeModel;
    import javax.swing.tree.TreeModel;
    import javax.swing.tree.TreePath;
    import tjacobs.ui.WindowUtilities;
    public class HiddenNodeTreeModel implements TreeModel {
         TreeModel mModel;
         ArrayList<Object> mHidden = new ArrayList<Object>();
         public HiddenNodeTreeModel (TreeModel model) {
              mModel = model;
         public void addTreeModelListener(TreeModelListener arg0) {
              mModel.addTreeModelListener(arg0);
         private ArrayList<Integer> getHiddenChildren(Object parent) {
              ArrayList<Integer> spots = new ArrayList<Integer>();
              Iterator _i = mHidden.iterator();
              while (_i.hasNext()) {
                   Object hidden = _i.next();
                   int idx = mModel.getIndexOfChild(parent, hidden);
                   if (idx != -1) {
                        spots.add(idx);
              return spots;
         public Object getChild(Object arg0, int index) {
              ArrayList<Integer> spots = getHiddenChildren(arg0);
              Collections.sort(spots);
              Iterator<Integer> _i = spots.iterator();
              while (_i.hasNext()) {
                   int num = _i.next();
                   if (num <= index) {
                        index++;
              return mModel.getChild(arg0, index);
         public int getChildCount(Object arg0) {
              ArrayList list = getHiddenChildren(arg0);
              System.out.println("size = " + list.size());
              return mModel.getChildCount(arg0) - list.size();
         public int getIndexOfChild(Object arg0, Object arg1) {
              int index = mModel.getIndexOfChild(arg0, arg1);
              ArrayList<Integer> spots = getHiddenChildren(arg0);
              Collections.sort(spots);
              Iterator<Integer> _i = spots.iterator();
              int toSub = 0;
              while (_i.hasNext()) {
                   int num = _i.next();
                   if (num <= index) {
                        toSub++;
              return index - toSub;
         public Object getRoot() {
              // TODO Auto-generated method stub
              return mModel.getRoot();
         public boolean isLeaf(Object arg0) {
              // TODO Auto-generated method stub
              return mModel.isLeaf(arg0);
         public void removeTreeModelListener(TreeModelListener arg0) {
              mModel.removeTreeModelListener(arg0);
         public void valueForPathChanged(TreePath arg0, Object arg1) {
              mModel.valueForPathChanged(arg0, arg1);
         public void hideNode(Object node) {
              if (node instanceof TreePath) {
                   node = ((TreePath)node).getLastPathComponent();
              mHidden.add(node);
         public void showNode(Object node) {
              mHidden.remove(node);
         public void showAll() {
              mHidden.clear();
          * @param args
         public static void main(String[] args) {
              // TODO Auto-generated method stub
              DefaultMutableTreeNode A = new DefaultMutableTreeNode("A");
              DefaultMutableTreeNode B = new DefaultMutableTreeNode("B");
              DefaultMutableTreeNode C = new DefaultMutableTreeNode("C");
              DefaultMutableTreeNode D = new DefaultMutableTreeNode("D");
              DefaultMutableTreeNode E = new DefaultMutableTreeNode("E");
              DefaultMutableTreeNode F = new DefaultMutableTreeNode("F");
              A.add(B);
              B.add(C);
              B.add(D);
              B.add(E);
              E.add(F);
              DefaultTreeModel model = new DefaultTreeModel(A);
              final HiddenNodeTreeModel hmodel = new HiddenNodeTreeModel(model);
              final JTree tree = new JTree(hmodel);
              JFrame jf = new JFrame("HiddenNodeTreeModel Test");
              jf.add(tree);
              JMenuBar bar = new JMenuBar();
              jf.setJMenuBar(bar);
              JMenu menu = new JMenu("Options");
              bar.add(menu);
              final JMenuItem hide = new JMenuItem("Hide");
              final JMenuItem show = new JMenuItem("ShowAll");
              menu.add(hide);
              menu.add(show);
              ActionListener al = new ActionListener() {
                   public void actionPerformed(ActionEvent ae) {
                        if (ae.getSource() == hide) {
                             hmodel.hideNode(tree.getSelectionPath());
                             tree.updateUI();
                        else {
                             hmodel.showAll();
                             tree.updateUI();
              hide.addActionListener(al);
              show.addActionListener(al);
              jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              jf.setBounds(100,100,100,100);
              jf.setVisible(true);
    }

  • Display JTree in browser using JSP

    i have a program that converts xml file in to tree structure(using Swing). When i run this using eclipse then it is working. Swing is an extension of applet , right. I want to embed this in an HTML page(JSP). so that i can display the tree structure. Its gives class not foung error.
    It is not posiible to embed it. I think if it extends an Applet then it will display. But i don't know how to convert that. It gives error if i convert.
    pls help
    CODE:
    package TreeGen;
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    import org.xml.sax.SAXException;
    import java.io.IOException;
    import org.w3c.dom.Document;
    // Basic GUI components
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTree;
    // GUI components for right-hand side
    import javax.swing.JSplitPane;
    import javax.swing.JEditorPane;
    // GUI support classes
    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.Toolkit;
    import java.awt.event.WindowEvent;
    import java.awt.event.WindowAdapter;
    // For creating borders
    import javax.swing.border.EmptyBorder;
    import javax.swing.border.BevelBorder;
    import javax.swing.border.CompoundBorder;
    // For creating a TreeModel
    import javax.swing.tree.*;
    import javax.swing.event.*;
    import java.util.*;
    public class TreeGen extends JPanel
         static Document document;
         boolean compress = false;
         static final int windowHeight = 660;
         static final int leftWidth = 300;
         static final int rightWidth = 640;
         static final int windowWidth = leftWidth + rightWidth;
         public TreeGen()
         EmptyBorder eb = new EmptyBorder(5,5,5,5);
         BevelBorder bb = new BevelBorder(BevelBorder.LOWERED);
         CompoundBorder cb = new CompoundBorder(eb,bb);
         this.setBorder(new CompoundBorder(cb,eb));
         JTree tree = new JTree(new DomToTreeModelAdapter());
         JScrollPane treeView = new JScrollPane(tree);
         treeView.setPreferredSize(
              new Dimension( leftWidth, windowHeight ));
         final
         JEditorPane htmlPane = new JEditorPane("text/html","");
         htmlPane.setEditable(true);
         JScrollPane htmlView = new JScrollPane(htmlPane);
         htmlView.setPreferredSize(
              new Dimension( rightWidth, windowHeight ));
         tree.addTreeSelectionListener(
              new TreeSelectionListener()
              public void valueChanged(TreeSelectionEvent e)
                   TreePath p = e.getNewLeadSelectionPath();
                   if (p != null)
                   AdapterNode adpNode =
                        (AdapterNode) p.getLastPathComponent();
                   htmlPane.setText(adpNode.content());
         JSplitPane splitPane =
              new JSplitPane( JSplitPane.HORIZONTAL_SPLIT,
                                  treeView,
                                  htmlView );
         splitPane.setContinuousLayout( false );
         splitPane.setDividerLocation( leftWidth );
         splitPane.setDividerSize(1);
         splitPane.setPreferredSize(
                   new Dimension( windowWidth + 10, windowHeight+10 ));
         this.setLayout(new BorderLayout());
         this.add("Center", splitPane );
         //return menuBar;
         } // constructor
         public static void main(String argv[])
              DocumentBuilderFactory factory =
                   DocumentBuilderFactory.newInstance();
              try {
              DocumentBuilder builder = factory.newDocumentBuilder();
              document = builder.parse("C:/Program Files/Apache Software Foundation/Tomcat 5.0/webapps/parser1/sample.xml");
                   makeFrame();
              } catch (SAXException sxe){
                   System.out.println("ERROR");
              Exception x = sxe;
              if (sxe.getException() != null)
                   x = sxe.getException();
              x.printStackTrace();
              } catch (ParserConfigurationException pce) {
                   pce.printStackTrace();
              } catch (IOException ioe) {
              ioe.printStackTrace();
         } // main
         public static void makeFrame()
              JFrame frame = new JFrame("DOM Echo");
              frame.addWindowListener(
              new WindowAdapter() {
                   public void windowClosing(WindowEvent e) {System.exit(0);}
              final TreeGen echoPanel =
              new TreeGen();
              frame.getContentPane().add("Center", echoPanel );
              frame.pack();
              Dimension screenSize =
              Toolkit.getDefaultToolkit().getScreenSize();
              int w = windowWidth + 10;
              int h = windowHeight + 10;
              frame.setSize(w, h);
              frame.setVisible(true);
         } // makeFrame
         static final String[] typeName = {
              "none",
              "Element",
              "Attr",
              "Text",
              "CDATA",
              "EntityRef",
              "Entity",
              "ProcInstr",
              "Comment",
              "Document",
              "DocType",
              "DocFragment",
              "Notation",
         static final int ELEMENT_TYPE = 1;
         static final int ATTR_TYPE = 2;
         static final int TEXT_TYPE = 3;
         static final int CDATA_TYPE = 4;
         static final int ENTITYREF_TYPE = 5;
         static final int ENTITY_TYPE = 6;
         static final int PROCINSTR_TYPE = 7;
         static final int COMMENT_TYPE = 8;
         static final int DOCUMENT_TYPE = 9;
         static final int DOCTYPE_TYPE = 10;
         static final int DOCFRAG_TYPE = 11;
         static final int NOTATION_TYPE = 12;
    static String[] treeElementNames = {
              "slideshow",
              "slide",
              "title", // For slideshow #1
              "slide-title", // For slideshow #10
              "item",
         boolean treeElement(String elementName) {
         for (int i=0; i<treeElementNames.length; i++) {
              //System.out.println(treeElementNames);
              if ( elementName.equals(treeElementNames[i]) )
              return true;
         return false;
         public class AdapterNode
         org.w3c.dom.Node domNode;
         public AdapterNode(org.w3c.dom.Node node)
              domNode = node;
         public String toString()
              String s = typeName[domNode.getNodeType()];
              String nodeName = domNode.getNodeName();
              if (! nodeName.startsWith("#"))
              s += ": " + nodeName;
              if (compress)
              String t = content().trim();
              int x = t.indexOf("\n");
              if (x >= 0) t = t.substring(0, x);
              s += " " + t;
              return s;
              if (domNode.getNodeValue() != null)
              if (s.startsWith("ProcInstr"))
                   s += ", ";
              else
                   s += ": ";
              // Trim the value to get rid of NL's at the front
              String t = domNode.getNodeValue().trim();
              int x = t.indexOf("\n");
              if (x >= 0) t = t.substring(0, x);
              s += t;
              return s;
         public String content()
              String s = "";
              org.w3c.dom.NodeList nodeList = domNode.getChildNodes();
              for (int i=0; i<nodeList.getLength(); i++)
              org.w3c.dom.Node node = nodeList.item(i);
              int type = node.getNodeType();
              //System.out.println(type);
              AdapterNode adpNode = new AdapterNode(node); //inefficient, but works
              if (type == ELEMENT_TYPE)
                   if ( treeElement(node.getNodeName()) ) continue;
                   s += "<" + node.getNodeName() + ">";
                   s += adpNode.content();
                   s += "</" + node.getNodeName() + ">";
              else if (type == TEXT_TYPE)
                   s += node.getNodeValue();
              else if (type == ENTITYREF_TYPE)
                   s += adpNode.content();
              else if (type == CDATA_TYPE)
                   StringBuffer sb = new StringBuffer( node.getNodeValue() );
                   for (int j=0; j<sb.length(); j++)
                   if (sb.charAt(j) == '<')
                        sb.setCharAt(j, '&');
                        sb.insert(j+1, "lt;");
                        j += 3;
                   else if (sb.charAt(j) == '&')
                        sb.setCharAt(j, '&');
                        sb.insert(j+1, "amp;");
                        j += 4;
                   s += "<pre>" + sb + "\n</pre>";
              return s;
         public int index(AdapterNode child)
              int count = childCount();
              for (int i=0; i<count; i++)
              AdapterNode n = this.child(i);
              if (child.domNode == n.domNode) return i;
              return -1; // Should never get here.
         public AdapterNode child(int searchIndex)
              org.w3c.dom.Node node =
                   domNode.getChildNodes().item(searchIndex);
              if (compress)
              int elementNodeIndex = 0;
              for (int i=0; i<domNode.getChildNodes().getLength(); i++)
                   node = domNode.getChildNodes().item(i);
                   if (node.getNodeType() == ELEMENT_TYPE
                   && treeElement( node.getNodeName() )
                   && elementNodeIndex++ == searchIndex)
                   break;
              return new AdapterNode(node);
         public int childCount()
              if (!compress)
              return domNode.getChildNodes().getLength();
              int count = 0;
              for (int i=0; i<domNode.getChildNodes().getLength(); i++)
              org.w3c.dom.Node node = domNode.getChildNodes().item(i);
              if (node.getNodeType() == ELEMENT_TYPE
              && treeElement( node.getNodeName() ))
                   ++count;
              return count;
         public class DomToTreeModelAdapter
         implements javax.swing.tree.TreeModel
         public Object getRoot()
              return new AdapterNode(document);
         public boolean isLeaf(Object aNode)
              AdapterNode node = (AdapterNode) aNode;
              if (node.childCount() > 0) return false;
              return true;
         public int getChildCount(Object parent)
              AdapterNode node = (AdapterNode) parent;
              return node.childCount();
         public Object getChild(Object parent, int index)
              AdapterNode node = (AdapterNode) parent;
              return node.child(index);
         public int getIndexOfChild(Object parent, Object child)
              AdapterNode node = (AdapterNode) parent;
              return node.index((AdapterNode) child);
         public void valueForPathChanged(TreePath path, Object newValue)
         private Vector listenerList = new Vector();
         public void addTreeModelListener(TreeModelListener listener)
              if ( listener != null
              && ! listenerList.contains( listener ) )
              listenerList.addElement( listener );
         public void removeTreeModelListener(TreeModelListener listener)
              if ( listener != null )
              listenerList.removeElement( listener );
         public void fireTreeNodesChanged( TreeModelEvent e )
              Enumeration listeners = listenerList.elements();
              while ( listeners.hasMoreElements() )
              TreeModelListener listener =
                   (TreeModelListener) listeners.nextElement();
              listener.treeNodesChanged( e );
         public void fireTreeNodesInserted( TreeModelEvent e )
              Enumeration listeners = listenerList.elements();
              while ( listeners.hasMoreElements() )
              TreeModelListener listener =
                   (TreeModelListener) listeners.nextElement();
              listener.treeNodesInserted( e );
         public void fireTreeNodesRemoved( TreeModelEvent e )
              Enumeration listeners = listenerList.elements();
              while ( listeners.hasMoreElements() )
              TreeModelListener listener =
                   (TreeModelListener) listeners.nextElement();
              listener.treeNodesRemoved( e );
         public void fireTreeStructureChanged( TreeModelEvent e )
              Enumeration listeners = listenerList.elements();
              while ( listeners.hasMoreElements() )
              TreeModelListener listener =
                   (TreeModelListener) listeners.nextElement();
              listener.treeStructureChanged( e );

    I actually had to do this a few months ago. There are ways to perform this kind display using various distributed object (i.e., using MS Word OLE objects to "interpret" the byte for you, etc.). But this soon got extremely difficult to manage (and I actually had to use Perl/CGI for the majority of it).
    The solution I went with was to implement a "cache" directory on the web server. Basically, the JSP/Servlet can simply check the cache and if file not there, create it from the database. Then send a redirect back to the browser to this newly-created file. The browser will then appropriately open the document. I tested this with both Netscape and IE browsers and common MIME types such as text files, MS Office docs, zip files, PDFs, RTFs.
    Not ideal, but unfortunately the best I came up with.

  • Display tree in applet

    i have a program to convert Xml to tree structure. But i am not able to call it in JSP. So i want to convert to applet. how to convert it.
    package TreeGen;
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.FactoryConfigurationError;
    import javax.xml.parsers.ParserConfigurationException;
    import org.xml.sax.SAXException;
    import org.xml.sax.SAXParseException;
    import java.io.File;
    import java.io.IOException;
    import org.w3c.dom.Document;
    import org.w3c.dom.DOMException;
    import org.w3c.dom.Element;
    // Basic GUI components
    import javax.swing.JApplet;
    import javax.swing.JFrame;
    import javax.swing.JMenu;
    import javax.swing.JMenuBar;
    import javax.swing.JMenuItem;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTree;
    // GUI components for right-hand side
    import javax.swing.JSplitPane;
    import javax.swing.JEditorPane;
    // GUI support classes
    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.Toolkit;
    import java.awt.event.KeyEvent;
    import java.awt.event.WindowEvent;
    import java.awt.event.WindowAdapter;
    // For creating borders
    import javax.swing.border.EmptyBorder;
    import javax.swing.border.BevelBorder;
    import javax.swing.border.CompoundBorder;
    // For creating a TreeModel
    import javax.swing.tree.*;
    import javax.swing.event.*;
    import java.util.*;
    import java.applet.*;
    public class TreeGen extends JPanel
         static Document document;
         boolean compress = false;
         static final int windowHeight = 660;
         static final int leftWidth = 300;
         static final int rightWidth = 640;
         static final int windowWidth = leftWidth + rightWidth;
         public TreeGen()
         EmptyBorder eb = new EmptyBorder(5,5,5,5);
         BevelBorder bb = new BevelBorder(BevelBorder.LOWERED);
         CompoundBorder cb = new CompoundBorder(eb,bb);
         this.setBorder(new CompoundBorder(cb,eb));
         JTree tree = new JTree(new DomToTreeModelAdapter());
         JScrollPane treeView = new JScrollPane(tree);
         treeView.setPreferredSize(
              new Dimension( leftWidth, windowHeight ));
         final
         JEditorPane htmlPane = new JEditorPane("text/html","");
         htmlPane.setEditable(true);
         JScrollPane htmlView = new JScrollPane(htmlPane);
         htmlView.setPreferredSize(
              new Dimension( rightWidth, windowHeight ));
         tree.addTreeSelectionListener(
              new TreeSelectionListener()
              public void valueChanged(TreeSelectionEvent e)
                   TreePath p = e.getNewLeadSelectionPath();
                   if (p != null)
                   AdapterNode adpNode =
                        (AdapterNode) p.getLastPathComponent();
                   htmlPane.setText(adpNode.content());
         JSplitPane splitPane =
              new JSplitPane( JSplitPane.HORIZONTAL_SPLIT,
                                  treeView,
                                  htmlView );
         splitPane.setContinuousLayout( false );
         splitPane.setDividerLocation( leftWidth );
         splitPane.setDividerSize(1);
         splitPane.setPreferredSize(
                   new Dimension( windowWidth + 10, windowHeight+10 ));
         this.setLayout(new BorderLayout());
         this.add("Center", splitPane );
         //return menuBar;
         } // constructor
         public static void main(String argv[])
              DocumentBuilderFactory factory =
                   DocumentBuilderFactory.newInstance();
              try {
              DocumentBuilder builder = factory.newDocumentBuilder();
              document = builder.parse("C:/Program Files/Apache Software Foundation/Tomcat 5.0/webapps/parser1/sample.xml");
                   makeFrame();
              } catch (SAXException sxe){
                   System.out.println("ERROR");
              Exception x = sxe;
              if (sxe.getException() != null)
                   x = sxe.getException();
              x.printStackTrace();
              } catch (ParserConfigurationException pce) {
                   pce.printStackTrace();
              } catch (IOException ioe) {
              ioe.printStackTrace();
         } // main
         public static void makeFrame()
              //JApplet app = new JApplet();
              //app.add
              JFrame frame = new JFrame("DOM Echo");
              frame.addWindowListener(
              new WindowAdapter() {
                   public void windowClosing(WindowEvent e) {System.exit(0);}
              final TreeGen echoPanel =
              new TreeGen();
              frame.getContentPane().add("Center", echoPanel );
              frame.pack();
              Dimension screenSize =
              Toolkit.getDefaultToolkit().getScreenSize();
              int w = windowWidth + 10;
              int h = windowHeight + 10;
              //TreeGen tg = new TreeGen();
              //MenuDemo demo = new MenuDemo();
              //frame.setJMenuBar(demo.createMenuBar());
              //frame.setContentPane(demo.createContentPane());
              //Display the window.
              frame.setSize(w, h);
              frame.setVisible(true);
         } // makeFrame
         static final String[] typeName = {
              "none",
              "Element",
              "Attr",
              "Text",
              "CDATA",
              "EntityRef",
              "Entity",
              "ProcInstr",
              "Comment",
              "Document",
              "DocType",
              "DocFragment",
              "Notation",
         static final int ELEMENT_TYPE = 1;
         static final int ATTR_TYPE = 2;
         static final int TEXT_TYPE = 3;
         static final int CDATA_TYPE = 4;
         static final int ENTITYREF_TYPE = 5;
         static final int ENTITY_TYPE = 6;
         static final int PROCINSTR_TYPE = 7;
         static final int COMMENT_TYPE = 8;
         static final int DOCUMENT_TYPE = 9;
         static final int DOCTYPE_TYPE = 10;
         static final int DOCFRAG_TYPE = 11;
         static final int NOTATION_TYPE = 12;
    static String[] treeElementNames = {
              "slideshow",
              "slide",
              "title", // For slideshow #1
              "slide-title", // For slideshow #10
              "item",
         boolean treeElement(String elementName) {
         for (int i=0; i<treeElementNames.length; i++) {
              //System.out.println(treeElementNames);
              if ( elementName.equals(treeElementNames[i]) )
              return true;
         return false;
         public class AdapterNode
         org.w3c.dom.Node domNode;
         public AdapterNode(org.w3c.dom.Node node)
              domNode = node;
         public String toString()
              String s = typeName[domNode.getNodeType()];
              String nodeName = domNode.getNodeName();
              if (! nodeName.startsWith("#"))
              s += ": " + nodeName;
              if (compress)
              String t = content().trim();
              int x = t.indexOf("\n");
              if (x >= 0) t = t.substring(0, x);
              s += " " + t;
              return s;
              if (domNode.getNodeValue() != null)
              if (s.startsWith("ProcInstr"))
                   s += ", ";
              else
                   s += ": ";
              // Trim the value to get rid of NL's at the front
              String t = domNode.getNodeValue().trim();
              int x = t.indexOf("\n");
              if (x >= 0) t = t.substring(0, x);
              s += t;
              return s;
         public String content()
              String s = "";
              org.w3c.dom.NodeList nodeList = domNode.getChildNodes();
              for (int i=0; i<nodeList.getLength(); i++)
              org.w3c.dom.Node node = nodeList.item(i);
              int type = node.getNodeType();
              //System.out.println(type);
              AdapterNode adpNode = new AdapterNode(node); //inefficient, but works
              if (type == ELEMENT_TYPE)
                   if ( treeElement(node.getNodeName()) ) continue;
                   s += "<" + node.getNodeName() + ">";
                   s += adpNode.content();
                   s += "</" + node.getNodeName() + ">";
              else if (type == TEXT_TYPE)
                   s += node.getNodeValue();
              else if (type == ENTITYREF_TYPE)
                   s += adpNode.content();
              else if (type == CDATA_TYPE)
                   StringBuffer sb = new StringBuffer( node.getNodeValue() );
                   for (int j=0; j<sb.length(); j++)
                   if (sb.charAt(j) == '<')
                        sb.setCharAt(j, '&');
                        sb.insert(j+1, "lt;");
                        j += 3;
                   else if (sb.charAt(j) == '&')
                        sb.setCharAt(j, '&');
                        sb.insert(j+1, "amp;");
                        j += 4;
                   s += "<pre>" + sb + "\n</pre>";
              return s;
         public int index(AdapterNode child)
              int count = childCount();
              for (int i=0; i<count; i++)
              AdapterNode n = this.child(i);
              if (child.domNode == n.domNode) return i;
              return -1; // Should never get here.
         public AdapterNode child(int searchIndex)
              org.w3c.dom.Node node =
                   domNode.getChildNodes().item(searchIndex);
              if (compress)
              int elementNodeIndex = 0;
              for (int i=0; i<domNode.getChildNodes().getLength(); i++)
                   node = domNode.getChildNodes().item(i);
                   if (node.getNodeType() == ELEMENT_TYPE
                   && treeElement( node.getNodeName() )
                   && elementNodeIndex++ == searchIndex)
                   break;
              return new AdapterNode(node);
         public int childCount()
              if (!compress)
              return domNode.getChildNodes().getLength();
              int count = 0;
              for (int i=0; i<domNode.getChildNodes().getLength(); i++)
              org.w3c.dom.Node node = domNode.getChildNodes().item(i);
              if (node.getNodeType() == ELEMENT_TYPE
              && treeElement( node.getNodeName() ))
                   ++count;
              return count;
         public class DomToTreeModelAdapter
         implements javax.swing.tree.TreeModel
         public Object getRoot()
              return new AdapterNode(document);
         public boolean isLeaf(Object aNode)
              AdapterNode node = (AdapterNode) aNode;
              if (node.childCount() > 0) return false;
              return true;
         public int getChildCount(Object parent)
              AdapterNode node = (AdapterNode) parent;
              return node.childCount();
         public Object getChild(Object parent, int index)
              AdapterNode node = (AdapterNode) parent;
              return node.child(index);
         public int getIndexOfChild(Object parent, Object child)
              AdapterNode node = (AdapterNode) parent;
              return node.index((AdapterNode) child);
         public void valueForPathChanged(TreePath path, Object newValue)
         private Vector listenerList = new Vector();
         public void addTreeModelListener(TreeModelListener listener)
              if ( listener != null
              && ! listenerList.contains( listener ) )
              listenerList.addElement( listener );
         public void removeTreeModelListener(TreeModelListener listener)
              if ( listener != null )
              listenerList.removeElement( listener );
         public void fireTreeNodesChanged( TreeModelEvent e )
              Enumeration listeners = listenerList.elements();
              while ( listeners.hasMoreElements() )
              TreeModelListener listener =
                   (TreeModelListener) listeners.nextElement();
              listener.treeNodesChanged( e );
         public void fireTreeNodesInserted( TreeModelEvent e )
              Enumeration listeners = listenerList.elements();
              while ( listeners.hasMoreElements() )
              TreeModelListener listener =
                   (TreeModelListener) listeners.nextElement();
              listener.treeNodesInserted( e );
         public void fireTreeNodesRemoved( TreeModelEvent e )
              Enumeration listeners = listenerList.elements();
              while ( listeners.hasMoreElements() )
              TreeModelListener listener =
                   (TreeModelListener) listeners.nextElement();
              listener.treeNodesRemoved( e );
         public void fireTreeStructureChanged( TreeModelEvent e )
              Enumeration listeners = listenerList.elements();
              while ( listeners.hasMoreElements() )
              TreeModelListener listener =
                   (TreeModelListener) listeners.nextElement();
              listener.treeStructureChanged( e );
    pls help.
    ramya

    There's already some applet code in there, although it's commented out. Did you add that?
    Anyway, the general principle for turning an app into an applet, is to replace the main() method with the Applet's (or JApplet's) init(), start(), and stop() methods. Also you won't be able to read data off the file system; use resources instead. (e.g., java.lang.Class.getResource)
    I'm not sure what this has to do with JSP.
    When you post code, please wrap it in &#91;code]&#91;/code] tags.

  • Help with building a JTree using tree node and node renderers

    Hi,
    I am having a few problems with JTree's. basically I want to build JTree from a web spider. The webspide searches a website checking links and stores the current url that is being processed as a string in the variable msg. I wan to use this variable to build a JTree in a new class and then add it to my GUI. I have created a tree node class and a renderer node class, these classes are built fine. can someone point me in the direction for actually using these to build my tree in a seperate class and then displaying it in a GUI class?
    *nodeRenderer.java
    import javax.swing.*;
    import javax.swing.tree.*;
    import java.awt.*;
    import java.net.*;
    public class nodeRenderer extends DefaultTreeCellRenderer
                                       implements TreeCellRenderer
    public static Icon icon= null;
    public nodeRenderer() {
    icon = new ImageIcon(getClass().getResource("icon.gif"));
    public Component getTreeCellRendererComponent(
    JTree tree,
    Object value,
    boolean sel,
    boolean expanded,
    boolean leaf,
    int row,
    boolean hasFocus) {
    super.getTreeCellRendererComponent(
    tree, value, sel,
    expanded, leaf, row,
    hasFocus);
    treeNode node = (treeNode)(((DefaultMutableTreeNode)value).getUserObject());
    if(icon != null) // set a custom icon
    setOpenIcon(icon);
    setClosedIcon(icon);
    setLeafIcon(icon);
         return this;
    *treeNode.java
    *this is the class to represent a node
    import javax.swing.*;
    import javax.swing.tree.*;
    import java.util.*;
    import java.net.*;
    * Class used to hold information about a web site that has
    * been searched by the spider class
    public class treeNode
    *Url from the WebSpiderController Class
    *that is currently being processed
    public String msg;
    treeNode(String urlText)
         msg = urlText;
    String getUrlText()
         return msg;
    //gui.java
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.tree.*;
    import java.net.*;
    import java.io.*;
    import java.util.*;
    public class gui extends JFrame implements Runnable
         *declare variable, boolean
         *thread, a object and a center
         *pane
         protected URL urlInput;
         protected Thread bgThread;
         protected boolean run = false;
         protected WebSpider webSpider;
         public gui()
              *create the gui here
              setTitle("Testing Tool");
         setSize(600,600);
         //add Buttons to the tool bar
         start.setText("Start");
         start.setActionCommand("Start");
         toolBar.add(start);
         ButtonListener startListener = new ButtonListener();
              start.addActionListener(startListener);
              cancel.setText("Cancel");
         cancel.setActionCommand("Cancel");
         toolBar.add(cancel);
         ButtonListener cancelListener = new ButtonListener();
              cancel.addActionListener(cancelListener);
              close.setText("Close");
         close.setActionCommand("Close");
         toolBar.add(close);
         ButtonListener closeListener = new ButtonListener();
              close.addActionListener(closeListener);
              //creat a simple form
              urlLabel.setText("Enter URL:");
              urlLabel.setBounds(100,36,288,24);
              formTab.add(urlLabel);
              url.setBounds(170,36,288,24);
              formTab.add(url);
              current.setText("Currently Processing: ");
              current.setBounds(100,80,288,24);
              formTab.add(current);
         //add scroll bars to the error messages screen and website structure
         errorPane.setAutoscrolls(true);
         errorPane.setHorizontalScrollBarPolicy(javax.swing.
         ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
         errorPane.setVerticalScrollBarPolicy(javax.swing.
         ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
         errorPane.setOpaque(true);
         errorTab.add(errorPane);
         errorPane.setBounds(0,0,580,490);
         errorText.setEditable(false);
         errorPane.getViewport().add(errorText);
         errorText.setBounds(0,0,600,550);
         treePane.setAutoscrolls(true);
         treePane.setHorizontalScrollBarPolicy(javax.swing.
         ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
         treePane.setVerticalScrollBarPolicy(javax.swing.
         ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
         treePane.setOpaque(true);
         treeTab.add(treePane);
         treePane.setBounds(0,0,580,490);
         treeText.setEditable(false);
         treePane.getViewport().add(treeText);
         treeText.setBounds(0,0,600,550);
         //create the tabbed window           
    centerPane.setBorder(new javax.swing.border.EtchedBorder());
    formTab.setLayout(null);
    errorTab.setLayout(null);
    treeTab.setLayout(null);
    centerPane.addTab("Search Parameters", formTab);
    centerPane.addTab("Error Messages", errorTab);
    centerPane.addTab("Website Structure", treeTab);
              //add the tool bar and tabbed pane
              getContentPane().add(toolBar, java.awt.BorderLayout.NORTH);
    getContentPane().add(centerPane, java.awt.BorderLayout.CENTER);                    
              *create the tool bar pane, a center pane, add the buttons,
              *labels, tabs, a text field for user input here
              javax.swing.JPanel toolBar = new javax.swing.JPanel();
              javax.swing.JButton start = new javax.swing.JButton();
              javax.swing.JButton cancel = new javax.swing.JButton();
              javax.swing.JButton close = new javax.swing.JButton();      
              javax.swing.JTabbedPane centerPane = new javax.swing.JTabbedPane();
              javax.swing.JPanel formTab = new javax.swing.JPanel();
              javax.swing.JLabel urlLabel = new javax.swing.JLabel();
              javax.swing.JLabel current = new javax.swing.JLabel();
              javax.swing.JTextField url = new javax.swing.JTextField();
              javax.swing.JPanel errorTab = new javax.swing.JPanel();
              javax.swing.JTextArea errorText = new javax.swing.JTextArea();
              javax.swing.JScrollPane errorPane = new javax.swing.JScrollPane();
              javax.swing.JPanel treeTab = new javax.swing.JPanel();
              javax.swing.JTextArea treeText = new javax.swing.JTextArea();
              javax.swing.JScrollPane treePane = new javax.swing.JScrollPane();
              javax.swing.JTree searchTree = new javax.swing.JTree();
              *show the gui
              public static void main(String args[])
              (new gui()).setVisible(true);
         *listen for the button presses and set the
         *boolean flag depending on which button is pressed
         class ButtonListener implements ActionListener
              public void actionPerformed(ActionEvent event)
                   Object object = event.getSource();
                   if (object == start)
                        run = true;
                        startActionPerformed(event);
                   if (object == cancel)
                        run = false;
                        startActionPerformed(event);
                   if (object == close)
                        System.exit(0);
         *this method is called when the start or
         *cancel button is pressed.
         void startActionPerformed (ActionEvent event)
              if (run == true && bgThread == null)
                   bgThread = new Thread(this);
                   bgThread.start();
              if (run == false && bgThread != null)
                   webSpider.cancel();
         *this mehtod will start the background thred.
         *the background thread is required so that the
         *GUI is still displayed
         public void run()
              try
                   webSpider = new WebSpider(this);
                   webSpider.clear();
                   urlInput = new URL(url.getText());
                   webSpider.addURL(urlInput);
                   webSpider.run();
                   bgThread=null;
              catch (MalformedURLException e)
                   addressError addErr = new addressError();
                   addErr.addMsg = "URL ERROR - PLEASE CHECK";
                   SwingUtilities.invokeLater(addErr);
              *this method is called by the web spider
              *once a url is found. Validation of navigation
              *happens here.
              public boolean urlFound(URL urlInput,URL url)
                   CurrentlyProcessing pro = new CurrentlyProcessing();
              pro.msg = url.toString();
              SwingUtilities.invokeLater(pro);
              if (!testLink(url))
                        navigationError navErr = new navigationError();
                        navErr.navMsg = "Broken Link "+url+" caused on "+urlInput+"\n";
                        return false;
              if (!url.getHost().equalsIgnoreCase(urlInput.getHost()))
                   return false;
              else
                   return true;
              *this method is called internally to check
         *that a link works
              protected boolean testLink(URL url)
              try
                   URLConnection connection = url.openConnection();
                   connection.connect();
                   return true;
              catch (IOException e)
                   return false;
         *this method is called when an error is
         *found.
              public void URLError(URL url)
              *this method is called when an email
              *address is found
              public void emailFound(String email)
              /*this method will update any errors found inc
              *address errors and broken links
              class addressError implements Runnable
                   public String addMsg;
                   public void run()
                        errorText.append(addMsg);
                        current.setText("Currently Processing: "+ addMsg);
              class navigationError implements Runnable
                   public String navMsg;
                   public void run()
                        errorText.append(navMsg);
              *this method will update the currently
              *processing field on the GUI
              class CurrentlyProcessing implements Runnable
              public String msg;
              public void run()
                   current.setText("Currently Processing: " + msg );
    //webspider.java
    import java.util.*;
    import java.net.*;
    import java.io.*;
    import javax.swing.text.*;
    import javax.swing.text.html.*;
    import javax.swing.tree.*;
    import javax.swing.*;
    *this class implements the spider.
    public class WebSpider extends HTMLEditorKit
         *make a collection of the URL's
         protected Collection urlErrors = new ArrayList(3);
         protected Collection urlsWaiting = new ArrayList(3);
         protected Collection urlsProcessed = new ArrayList(3);
         //report URL's to this class
         protected gui report;
         *this flag will indicate whether the process
         *is to be cancelled
         protected boolean cancel = false;
         *The constructor
         *report the urls to the wui class
         public WebSpider(gui report)
         this.report = report;
         *get the urls from the above declared
         *collections
         public Collection getUrlErrors()
         return urlErrors;
         public Collection getUrlsWaiting()
         return urlsWaiting;
         public Collection getUrlsProcessed()
         return urlsProcessed;
         * Clear all of the collections.
         public void clear()
         getUrlErrors().clear();
         getUrlsWaiting().clear();
         getUrlsProcessed().clear();
         *Set a flag that will cause the begin
         *method to return before it is done.
         public void cancel()
         cancel = true;
         *add the entered url for porcessing
         public void addURL(URL url)
         if (getUrlsWaiting().contains(url))
              return;
         if (getUrlErrors().contains(url))
              return;
         if (getUrlsProcessed().contains(url))
              return;
         /*WRITE TO LOG FILE*/
         log("Adding to workload: " + url );
         getUrlsWaiting().add(url);
         *process a url
         public void processURL(URL url)
         try
              /*WRITE TO LOGFILE*/
              log("Processing: " + url );
              // get the URL's contents
              URLConnection connection = url.openConnection();
              if ((connection.getContentType()!=null) &&
         !connection.getContentType().toLowerCase().startsWith("text/"))
              getUrlsWaiting().remove(url);
              getUrlsProcessed().add(url);
              log("Not processing because content type is: " +
         connection.getContentType() );
                   return;
         // read the URL
         InputStream is = connection.getInputStream();
         Reader r = new InputStreamReader(is);
         // parse the URL
         HTMLEditorKit.Parser parse = new HTMLParse().getParser();
         parse.parse(r,new Parser(url),true);
    catch (IOException e)
         getUrlsWaiting().remove(url);
         getUrlErrors().add(url);
         log("Error: " + url );
         report.URLError(url);
         return;
    // mark URL as complete
    getUrlsWaiting().remove(url);
    getUrlsProcessed().add(url);
    log("Complete: " + url );
    *start the spider
    public void run()
    cancel = false;
    while (!getUrlsWaiting().isEmpty() && !cancel)
         Object list[] = getUrlsWaiting().toArray();
         for (int i=0;(i<list.length)&&!cancel;i++)
         processURL((URL)list);
    * A HTML parser callback used by this class to detect links
    protected class Parser extends HTMLEditorKit.ParserCallback
    protected URL urlInput;
    public Parser(URL urlInput)
    this.urlInput = urlInput;
    public void handleSimpleTag(HTML.Tag t,MutableAttributeSet a,int pos)
    String href = (String)a.getAttribute(HTML.Attribute.HREF);
    if((href==null) && (t==HTML.Tag.FRAME))
    href = (String)a.getAttribute(HTML.Attribute.SRC);
    if (href==null)
    return;
    int i = href.indexOf('#');
    if (i!=-1)
    href = href.substring(0,i);
    if (href.toLowerCase().startsWith("mailto:"))
    report.emailFound(href);
    return;
    handleLink(urlInput,href);
    public void handleStartTag(HTML.Tag t,MutableAttributeSet a,int pos)
    handleSimpleTag(t,a,pos); // handle the same way
    protected void handleLink(URL urlInput,String str)
    try
         URL url = new URL(urlInput,str);
    if (report.urlFound(urlInput,url))
    addURL(url);
    catch (MalformedURLException e)
    log("Found malformed URL: " + str);
    *log the information of the spider
    public void log(String entry)
    System.out.println( (new Date()) + ":" + entry );
    I have a seperate class for parseing the HTML. Any help would be greatly appreciated
    mrv

    Hi Sorry to be a pain again,
    I have re worked the gui class so it looks like this now:
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.tree.*;
    import javax.swing.event.*;
    import java.net.*;
    import java.io.*;
    import java.util.*;
    public class gui extends JFrame implements Runnable
         *declare variable, boolean
         *thread, a object and a center
         *pane
         protected URL urlInput;
         protected Thread bgThread;
         protected boolean run = false;
         protected WebSpider webSpider;
         public String msgInfo;
         public String brokenUrl;
         public String goodUrl;
         public String deadUrl;
         protected DefaultMutableTreeNode rootNode;
    protected DefaultTreeModel treeModel;
         public gui()
              *create the gui here
              setTitle("Testing Tool");
         setSize(600,600);
         //add Buttons to the tool bar
         start.setText("Start");
         start.setActionCommand("Start");
         toolBar.add(start);
         ButtonListener startListener = new ButtonListener();
              start.addActionListener(startListener);
              cancel.setText("Cancel");
         cancel.setActionCommand("Cancel");
         toolBar.add(cancel);
         ButtonListener cancelListener = new ButtonListener();
              cancel.addActionListener(cancelListener);
              close.setText("Close");
         close.setActionCommand("Close");
         toolBar.add(close);
         ButtonListener closeListener = new ButtonListener();
              close.addActionListener(closeListener);
              //creat a simple form
              urlLabel.setText("Enter URL:");
              urlLabel.setBounds(100,36,288,24);
              formTab.add(urlLabel);
              url.setBounds(170,36,288,24);
              formTab.add(url);
              current.setText("Currently Processing: ");
              current.setBounds(100,80,288,24);
              formTab.add(current);
         //add scroll bars to the error messages screen and website structure
         errorPane.setAutoscrolls(true);
         errorPane.setHorizontalScrollBarPolicy(javax.swing.
         ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
         errorPane.setVerticalScrollBarPolicy(javax.swing.
         ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
         errorPane.setOpaque(true);
         errorTab.add(errorPane);
         errorPane.setBounds(0,0,580,490);
         errorText.setEditable(false);
         errorPane.getViewport().add(errorText);
         errorText.setBounds(0,0,600,550);
         treePane.setAutoscrolls(true);
         treePane.setHorizontalScrollBarPolicy(javax.swing.
         ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
         treePane.setVerticalScrollBarPolicy(javax.swing.
         ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
         treePane.setOpaque(true);
         treeTab.add(treePane);
         treePane.setBounds(0,0,580,490);
         treeText.setEditable(false);
         treePane.getViewport().add(treeText);
         treeText.setBounds(0,0,600,550);
         //JTree
         // NEW CODE
         rootNode = new DefaultMutableTreeNode("Root Node");
         treeModel = new DefaultTreeModel(rootNode);
         treeModel.addTreeModelListener(new MyTreeModelListener());
         tree = new JTree(treeModel);
         tree.setEditable(true);
         tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
    tree.setShowsRootHandles(true);
         treeText.add(tree);
         //create the tabbed window           
    centerPane.setBorder(new javax.swing.border.EtchedBorder());
    formTab.setLayout(null);
    errorTab.setLayout(null);
    treeTab.setLayout(null);
    centerPane.addTab("Search Parameters", formTab);
    centerPane.addTab("Error Messages", errorTab);
    centerPane.addTab("Website Structure", treeTab);
              //add the tool bar and tabbed pane
              getContentPane().add(toolBar, java.awt.BorderLayout.NORTH);
    getContentPane().add(centerPane, java.awt.BorderLayout.CENTER);     
              *create the tool bar pane, a center pane, add the buttons,
              *labels, tabs, a text field for user input here
              javax.swing.JPanel toolBar = new javax.swing.JPanel();
              javax.swing.JButton start = new javax.swing.JButton();
              javax.swing.JButton cancel = new javax.swing.JButton();
              javax.swing.JButton close = new javax.swing.JButton();      
              javax.swing.JTabbedPane centerPane = new javax.swing.JTabbedPane();
              javax.swing.JPanel formTab = new javax.swing.JPanel();
              javax.swing.JLabel urlLabel = new javax.swing.JLabel();
              javax.swing.JLabel current = new javax.swing.JLabel();
              javax.swing.JTextField url = new javax.swing.JTextField();
              javax.swing.JPanel errorTab = new javax.swing.JPanel();
              javax.swing.JTextArea errorText = new javax.swing.JTextArea();
              javax.swing.JScrollPane errorPane = new javax.swing.JScrollPane();
              javax.swing.JPanel treeTab = new javax.swing.JPanel();
              javax.swing.JTextArea treeText = new javax.swing.JTextArea();
              javax.swing.JScrollPane treePane = new javax.swing.JScrollPane();
              javax.swing.JTree tree = new javax.swing.JTree();
              *show the gui
              public static void main(String args[])
              (new gui()).setVisible(true);
         *listen for the button presses and set the
         *boolean flag depending on which button is pressed
         class ButtonListener implements ActionListener
              public void actionPerformed(ActionEvent event)
                   Object object = event.getSource();
                   if (object == start)
                        run = true;
                        startActionPerformed(event);
                   if (object == cancel)
                        run = false;
                        startActionPerformed(event);
                   if (object == close)
                        System.exit(0);
         *this method is called when the start or
         *cancel button is pressed.
         void startActionPerformed (ActionEvent event)
              if (run == true && bgThread == null)
                   bgThread = new Thread(this);
                   bgThread.start();
                   //new line of code
                   treeText.addObject(msgInfo);
              if (run == false && bgThread != null)
                   webSpider.cancel();
         *this mehtod will start the background thred.
         *the background thread is required so that the
         *GUI is still displayed
         public void run()
              try
                   webSpider = new WebSpider(this);
                   webSpider.clear();
                   urlInput = new URL(url.getText());
                   webSpider.addURL(urlInput);
                   webSpider.run();
                   bgThread = null;
              catch (MalformedURLException e)
                   addressError addErr = new addressError();
                   addErr.addMsg = "URL ERROR - PLEASE CHECK";
                   SwingUtilities.invokeLater(addErr);
              *this method is called by the web spider
              *once a url is found. Validation of navigation
              *happens here.
              public boolean urlFound(URL urlInput,URL url)
                   CurrentlyProcessing pro = new CurrentlyProcessing();
              pro.msg = url.toString();
              SwingUtilities.invokeLater(pro);
              if (!testLink(url))
                        navigationError navErr = new navigationError();
                        navErr.navMsg = "Broken Link "+url+" caused on "+urlInput+"\n";
                        brokenUrl = url.toString();
                        return false;
              if (!url.getHost().equalsIgnoreCase(urlInput.getHost()))
                   return false;
              else
                   return true;
              *this method is returned if there is no link
              *on a web page, e.g. there us a dead end
              public void urlNotFound(URL urlInput)
                        deadEnd dEnd = new deadEnd();
                        dEnd.dEMsg = "No links on "+urlInput+"\n";
                        deadUrl = urlInput.toString();               
              *this method is called internally to check
         *that a link works
              protected boolean testLink(URL url)
              try
                   URLConnection connection = url.openConnection();
                   connection.connect();
                   goodUrl = url.toString();
                   return true;
              catch (IOException e)
                   return false;
         *this method is called when an error is
         *found.
              public void urlError(URL url)
              *this method is called when an email
              *address is found
              public void emailFound(String email)
              /*this method will update any errors found inc
              *address errors and broken links
              class addressError implements Runnable
                   public String addMsg;
                   public void run()
                        current.setText("Currently Processing: "+ addMsg);
                        errorText.append(addMsg);
              class navigationError implements Runnable
                   public String navMsg;
                   public void run()
                        errorText.append(navMsg);
              class deadEnd implements Runnable
                   public String dEMsg;
                   public void run()
                        errorText.append(dEMsg);
              *this method will update the currently
              *processing field on the GUI
              public class CurrentlyProcessing implements Runnable
                   public String msg;
              //new line
              public String msgInfo = msg;
              public void run()
                   current.setText("Currently Processing: " + msg );
         * NEW CODE
         * NEED THIS CODE SOMEWHERE
         * treeText.addObject(msgInfo);
         public DefaultMutableTreeNode addObject(Object child)
         DefaultMutableTreeNode parentNode = null;
         TreePath parentPath = tree.getSelectionPath();
         if (parentPath == null)
         parentNode = rootNode;
         else
         parentNode = (DefaultMutableTreeNode)
    (parentPath.getLastPathComponent());
         return addObject(parentNode, child, true);
         public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent,
    Object child)
         return addObject(parent, child, false);
         public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent,
         Object child,boolean shouldBeVisible)
         DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(child);
         if (parent == null)
         parent = rootNode;
         treeModel.insertNodeInto(childNode, parent, parent.getChildCount());
         if (shouldBeVisible)
         tree.scrollPathToVisible(new TreePath(childNode.getPath()));
              return childNode;
         public class MyTreeModelListener implements TreeModelListener
              public void treeNodesChanged (TreeModelEvent e)
                   DefaultMutableTreeNode node;
                   node = (DefaultMutableTreeNode)
                   (e.getTreePath().getLastPathComponent());
                   try
                        int index = e.getChildIndices()[0];
                        node = (DefaultMutableTreeNode)
                        (node.getChildAt(index));
                   catch (NullPointerException exc)
              public void treeNodesInserted(TreeModelEvent e)
              public void treeStructureChanged(TreeModelEvent e)
              public void treeNodesRemoved(TreeModelEvent e)
    I beleive that this line of code is required:
    treeText.addObject(msgInfo);
    I have placed it where the action events start the spider, but i keep getting this error:
    cannot resolve symbol
    symbol : method addObject (java.lang.String)
    location: class javax.swing.JTextArea
    treeText.addObject(msgInfo);
    Also the jtree is not showing the window that I want it to and I am not too sure why. could you have a look to see why? i think it needs a fresh pair of eyes.
    Many thanks
    MrV

  • JTree custom renderer setting selection background color problem

    Hi,
    I have a JTree with a custom icon renderer that displays an icon. The JTree is part of a TreeTable component. Iam having a problem setting the selection background uniformly for the entire row. There is no problem when there is no row selected in the JTable.
    My present code looks like this:
    Iam overriding paint in my renderer which extends DefaultCellRenderer.
           super.paint(g);
            Color bColor = null;
            if(!m_selected) {
                 if(currRow % 2 == 0) {
                      bColor = Color.WHITE;
                 } else {
                                                    bColor = backColor;
            } else {
                 bColor = table.getSelectionBackground();                  bColor = getRowSelectionColor();
         if(bColor != null) {
                           g.setColor(bColor);
             if(!m_selected) {
                   g.setXORMode(new Color(0xFF, 0xFF, 0xFF));
             } else {
                 g.setXORMode(new Color(0x00, 0x00, 0x00));
                  I have a color I arrive at using some algorithm that I want using method getRowSelectionColor(). The other cells in the row have this color. But the cell containing the tree node shows different color. Iam not able to arrive at the right combination of the color to set and the xor color so my tree node also looks like the other cells in the row.
    It is not a problem really as the table still looks good. Its just that the tree node looks like it has been highlighted and this might cause a problem when a table cell is highlighed later on in the application ( two cells in the row would be highlighted causing confusion).
    Any help would be appreciated.
    Regards,
    vidyut

    Hi Camickr,
    Thanks for the reply. Iam sorry I didn't include the sources the first time around. There were too many of them. I have created a small, self-contained, compilable program that demonstrates the problem and including it herewith. Still there's quite many files but they are all needed Iam afraid. The only one you will have to concern yourself fior this problem is the file IconRenderer.java. The treenode background and the other cells background are not in sync when table row is not selected in this example though. But they are in my real program. I just need them to be in sync i.e have the same background color when the row is selected.
    Your help would be very much appreciated.
    These are the files that are included below:
    1. AbstractTreeTableModel.java
    2. Bookmarks.java
    3. BookmarksModel.java
    4. DynamicTreeTableModel.java
    5. IconRenderer.java
    6. IndicatorRenderer.java
    7. JTreeTable.java
    8. TreeTableExample3.java (contains main)
    9. TreeTableModel.java
    10. TreeTableModelAdapter.java
    The copyright and javadocs information has been stripped for clarity.
    cheers,
    vidyut
    // AbstractTreeTableModel.java BEGIN
    import javax.swing.tree.*;
    import javax.swing.event.*;
    public abstract class AbstractTreeTableModel implements TreeTableModel {
        protected Object root;    
        protected EventListenerList listenerList = new EventListenerList();
        public AbstractTreeTableModel(Object root) {
            this.root = root;
        // Default implementations for methods in the TreeModel interface.
        public Object getRoot() {
            return root;
        public boolean isLeaf(Object node) {
            return getChildCount(node) == 0;
        public void valueForPathChanged(TreePath path, Object newValue) {}
        // This is not called in the JTree's default mode:
        // use a naive implementation.
        public int getIndexOfChild(Object parent, Object child) {
            for (int i = 0; i < getChildCount(parent); i++) {
             if (getChild(parent, i).equals(child)) {
                 return i;
         return -1;
        public void addTreeModelListener(TreeModelListener l) {
            listenerList.add(TreeModelListener.class, l);
        public void removeTreeModelListener(TreeModelListener l) {
            listenerList.remove(TreeModelListener.class, l);
        protected void fireTreeNodesChanged(Object source, Object[] path,
                                            int[] childIndices,
                                            Object[] children) {
            // Guaranteed to return a non-null array
            Object[] listeners = listenerList.getListenerList();
            TreeModelEvent e = null;
            // Process the listeners last to first, notifying
            // those that are interested in this event
            for (int i = listeners.length-2; i>=0; i-=2) {
                if (listeners==TreeModelListener.class) {
    // Lazily create the event:
    if (e == null)
    e = new TreeModelEvent(source, path,
    childIndices, children);
    ((TreeModelListener)listeners[i+1]).treeNodesChanged(e);
    protected void fireTreeNodesInserted(Object source, Object[] path,
    int[] childIndices,
    Object[] children) {
    // Guaranteed to return a non-null array
    Object[] listeners = listenerList.getListenerList();
    TreeModelEvent e = null;
    // Process the listeners last to first, notifying
    // those that are interested in this event
    for (int i = listeners.length-2; i>=0; i-=2) {
    if (listeners[i]==TreeModelListener.class) {
    // Lazily create the event:
    if (e == null)
    e = new TreeModelEvent(source, path,
    childIndices, children);
    ((TreeModelListener)listeners[i+1]).treeNodesInserted(e);
    protected void fireTreeNodesRemoved(Object source, Object[] path,
    int[] childIndices,
    Object[] children) {
    // Guaranteed to return a non-null array
    Object[] listeners = listenerList.getListenerList();
    TreeModelEvent e = null;
    // Process the listeners last to first, notifying
    // those that are interested in this event
    for (int i = listeners.length-2; i>=0; i-=2) {
    if (listeners[i]==TreeModelListener.class) {
    // Lazily create the event:
    if (e == null)
    e = new TreeModelEvent(source, path,
    childIndices, children);
    ((TreeModelListener)listeners[i+1]).treeNodesRemoved(e);
    protected void fireTreeStructureChanged(Object source, Object[] path,
    int[] childIndices,
    Object[] children) {
    // Guaranteed to return a non-null array
    Object[] listeners = listenerList.getListenerList();
    TreeModelEvent e = null;
    // Process the listeners last to first, notifying
    // those that are interested in this event
    for (int i = listeners.length-2; i>=0; i-=2) {
    if (listeners[i]==TreeModelListener.class) {
    // Lazily create the event:
    if (e == null)
    e = new TreeModelEvent(source, path,
    childIndices, children);
    ((TreeModelListener)listeners[i+1]).treeStructureChanged(e);
    // Default impelmentations for methods in the TreeTableModel interface.
    public Class getColumnClass(int column) { return Object.class; }
    public boolean isCellEditable(Object node, int column) {
    return getColumnClass(column) == TreeTableModel.class;
    public void setValueAt(Object aValue, Object node, int column) {}
    // Left to be implemented in the subclass:
    * public Object getChild(Object parent, int index)
    * public int getChildCount(Object parent)
    * public int getColumnCount()
    * public String getColumnName(Object node, int column)
    * public Object getValueAt(Object node, int column)
    // AbstractTreeTableModel.java END
    // Bookmarks.java BEGIN
    import java.io.*;
    import java.net.*;
    import java.util.*;
    import javax.swing.*;
    import javax.swing.tree.*;
    import javax.swing.text.*;
    import javax.swing.text.html.*;
    import javax.swing.text.html.parser.*;
    public class Bookmarks {
    /** The root node the bookmarks are added to. */
    private BookmarkDirectory root;
    * Creates a new Bookmarks object, with the entries coming from
    * <code>path</code>.
    public Bookmarks(String path) {
         root = new BookmarkDirectory("Bookmarks");
         if (path != null) {
         parse(path);
    * Returns the root of the bookmarks.
    public BookmarkDirectory getRoot() {
         return root;
    protected void parse(String path) {
         try {
         BufferedReader reader = new BufferedReader(new FileReader
                                       (path));
         new ParserDelegator().parse(reader, new CallbackHandler(), true);
         catch (IOException ioe) {
         System.out.println("IOE: " + ioe);
         JOptionPane.showMessageDialog(null, "Load Bookmarks",
                             "Unable to load bookmarks",
                             JOptionPane.ERROR_MESSAGE);
    private static final short NO_ENTRY = 0;
    private static final short BOOKMARK_ENTRY = 2;
    private static final short DIRECTORY_ENTRY = 3;
    private class CallbackHandler extends HTMLEditorKit.ParserCallback {
         /** Parent node that new entries are added to. */
         private BookmarkDirectory parent;
         /** The most recently parsed tag. */
         private HTML.Tag tag;
         /** The last tag encountered. */
         private HTML.Tag lastTag;
         * The state, will be one of NO_ENTRY, DIRECTORY_ENTRY,
    * or BOOKMARK_ENTRY.
         private short state;
         * Date for the next BookmarkDirectory node.
         private Date parentDate;
         * The values from the attributes are placed in here. When the
         * text is encountered this is added to the node hierarchy and a
    * new instance is created.
         private BookmarkEntry lastBookmark;
         * Creates the CallbackHandler.
         public CallbackHandler() {
         parent = root;
         lastBookmark = new BookmarkEntry();
         // HTMLEditorKit.ParserCallback methods
         * Invoked when text in the html document is encountered. Based on
         * the current state, this will either: do nothing
    * (state == NO_ENTRY),
         * create a new BookmarkEntry (state == BOOKMARK_ENTRY) or
    * create a new
         * BookmarkDirectory (state == DIRECTORY_ENTRY). If state is
    * != NO_ENTRY, it is reset to NO_ENTRY after this is
    * invoked.
    public void handleText(char[] data, int pos) {
         switch (state) {
         case NO_ENTRY:
              break;
         case BOOKMARK_ENTRY:
              // URL.
              lastBookmark.setName(new String(data));
    parent.add(lastBookmark);
    lastBookmark = new BookmarkEntry();
              break;
         case DIRECTORY_ENTRY:
              // directory.
              BookmarkDirectory newParent = new
                   BookmarkDirectory(new String(data));
              newParent.setCreated(parentDate);
              parent.add(newParent);
              parent = newParent;
              break;
         default:
              break;
    state = NO_ENTRY;
         * Invoked when a start tag is encountered. Based on the tag
         * this may update the BookmarkEntry and state, or update the
         * parentDate.
         public void handleStartTag(HTML.Tag t, MutableAttributeSet a,
                        int pos) {
         lastTag = tag;
         tag = t;
         if (t == HTML.Tag.A && lastTag == HTML.Tag.DT) {
    long lDate;
              // URL
              URL url;
              try {
              url = new URL((String)a.getAttribute(HTML.Attribute.HREF));
              } catch (MalformedURLException murle) {
              url = null;
              lastBookmark.setLocation(url);
              // created
              Date date;
              try {
    lDate = Long.parseLong((String)a.getAttribute("add_date"));
    if (lDate != 0l) {
    date = new Date(1000l * lDate);
    else {
    date = null;
              } catch (Exception ex) {
              date = null;
              lastBookmark.setCreated(date);
              // last visited
              try {
    lDate = Long.parseLong((String)a.
    getAttribute("last_visit"));
    if (lDate != 0l) {
    date = new Date(1000l * lDate);
    else {
    date = null;
              } catch (Exception ex) {
              date = null;
              lastBookmark.setLastVisited(date);
              state = BOOKMARK_ENTRY;
         else if (t == HTML.Tag.H3 && lastTag == HTML.Tag.DT) {
              // new node.
              try {
              parentDate = new Date(1000l * Long.parseLong((String)a.
                                  getAttribute("add_date")));
              } catch (Exception ex) {
              parentDate = null;
              state = DIRECTORY_ENTRY;
         * Invoked when the end of a tag is encountered. If the tag is
         * a DL, this will set the node that parents are added to the current
         * nodes parent.
         public void handleEndTag(HTML.Tag t, int pos) {
         if (t == HTML.Tag.DL && parent != null) {
              parent = (BookmarkDirectory)parent.getParent();
    public static class BookmarkDirectory extends DefaultMutableTreeNode {
         /** Dates created. */
         private Date created;
         public BookmarkDirectory(String name) {
         super(name);
         public void setName(String name) {
         setUserObject(name);
         public String getName() {
         return (String)getUserObject();
         public void setCreated(Date date) {
         this.created = date;
         public Date getCreated() {
         return created;
    public static class BookmarkEntry extends DefaultMutableTreeNode {
         /** User description of the string. */
         private String name;
         /** The URL the bookmark represents. */
         private URL location;
         /** Dates the URL was last visited. */
         private Date lastVisited;
         /** Date the URL was created. */
         private Date created;
         public void setName(String name) {
         this.name = name;
         public String getName() {
         return name;
         public void setLocation(URL location) {
         this.location = location;
         public URL getLocation() {
         return location;
         public void setLastVisited(Date date) {
         lastVisited = date;
         public Date getLastVisited() {
         return lastVisited;
         public void setCreated(Date date) {
         this.created = date;
         public Date getCreated() {
         return created;
         public String toString() {
         return getName();
    // Bookmarks.java END
    // BookmarksModel.java BEGIN
    import java.util.Date;
    public class BookmarksModel extends DynamicTreeTableModel {
    * Names of the columns.
    private static final String[] columnNames =
    { "Name", "Location", "Last Visited", "Created" };
    * Method names used to access the data to display.
    private static final String[] methodNames =
    { "getName", "getLocation", "getLastVisited","getCreated" };
    * Method names used to set the data.
    private static final String[] setterMethodNames =
    { "setName", "setLocation", "setLastVisited","setCreated" };
    private static final Class[] classes =
    { TreeTableModel.class, String.class, Date.class, Date.class };
    public BookmarksModel(Bookmarks.BookmarkDirectory root) {
         super(root, columnNames, methodNames, setterMethodNames, classes);
    public boolean isCellEditable(Object node, int column) {
         switch (column) {
         case 0:
         // Allow editing of the name, as long as not the root.
         return (node != getRoot());
         case 1:
         // Allow editing of the location, as long as not a
         // directory
         return (node instanceof Bookmarks.BookmarkEntry);
         default:
         // Don't allow editing of the date fields.
         return false;
    // BookmarksModel.java END
    // DynamicTreeTableModel.java BEGIN
    import java.lang.reflect.*;
    import javax.swing.tree.*;
    public class DynamicTreeTableModel extends AbstractTreeTableModel {
    /** Names of the columns, used for the TableModel getColumnName method. */
    private String[] columnNames;
    private String[] methodNames;
    private String[] setterMethodNames;
    /** Column classes, used for the TableModel method getColumnClass. */
    private Class[] cTypes;
    public DynamicTreeTableModel(TreeNode root, String[] columnNames,
                        String[] getterMethodNames,
                        String[] setterMethodNames,
                        Class[] cTypes) {
         super(root);
         this.columnNames = columnNames;
         this.methodNames = getterMethodNames;
         this.setterMethodNames = setterMethodNames;
         this.cTypes = cTypes;
    public int getChildCount(Object node) {
         return ((TreeNode)node).getChildCount();
    public Object getChild(Object node, int i) {
         return ((TreeNode)node).getChildAt(i);
    public boolean isLeaf(Object node) {
         return ((TreeNode)node).isLeaf();
    public int getColumnCount() {
         return columnNames.length;
    public String getColumnName(int column) {
         if (cTypes == null || column < 0 || column >= cTypes.length) {
         return null;
         return columnNames[column];
    public Class getColumnClass(int column) {
         if (cTypes == null || column < 0 || column >= cTypes.length) {
         return null;
         return cTypes[column];
    public Object getValueAt(Object node, int column) {
         try {
         Method method = node.getClass().getMethod(methodNames[column],
                                  null);
         if (method != null) {
              return method.invoke(node, null);
         catch (Throwable th) {}
         return null;
    * Returns true if there is a setter method name for column
    * <code>column</code>. This is set in the constructor.
    public boolean isCellEditable(Object node, int column) {
    return (setterMethodNames != null &&
         setterMethodNames[column] != null);
    // Note: This looks up the methods each time! This is rather inefficient;
    // it should really be changed to cache matching
    // methods/constructors
    // based on <code>node</code>'s class, and code>aValue</code>'s
    //class.
    public void setValueAt(Object aValue, Object node, int column) {
         boolean found = false;
         try {
         // We have to search through all the methods since the
         // types may not match up.
         Method[] methods = node.getClass().getMethods();
         for (int counter = methods.length - 1; counter >= 0; counter--) {
              if (methods[counter].getName().equals
              (setterMethodNames[column]) && methods[counter].
              getParameterTypes() != null && methods[counter].
              getParameterTypes().length == 1) {
              // We found a matching method
              Class param = methods[counter].getParameterTypes()[0];
              if (!param.isInstance(aValue)) {
                   // Yes, we can use the value passed in directly,
                   // no coercision is necessary!
                   if (aValue instanceof String &&
                   ((String)aValue).length() == 0) {
                   // Assume an empty string is null, this is
                   // probably bogus for here.
                   aValue = null;
                   else {
                   // Have to attempt some sort of coercision.
                   // See if the expected parameter type has
                   // a constructor that takes a String.
                   Constructor cs = param.getConstructor
                   (new Class[] { String.class });
                   if (cs != null) {
                        aValue = cs.newInstance(new Object[]
                                       { aValue });
                   else {
                        aValue = null;
              // null either means it was an empty string, or there
              // was no translation. Could potentially deal with these
              // differently.
              methods[counter].invoke(node, new Object[] { aValue });
              found = true;
              break;
         } catch (Throwable th) {
         System.out.println("exception: " + th);
         if (found) {
         // The value changed, fire an event to notify listeners.
         TreeNode parent = ((TreeNode)node).getParent();
         fireTreeNodesChanged(this, getPathToRoot(parent),
                        new int[] { getIndexOfChild(parent, node) },
                        new Object[] { node });
    public TreeNode[] getPathToRoot(TreeNode aNode) {
    return getPathToRoot(aNode, 0);
    private TreeNode[] getPathToRoot(TreeNode aNode, int depth) {
    TreeNode[] retNodes;
         // This method recurses, traversing towards the root in order
         // size the array. On the way back, it fills in the nodes,
         // starting from the root and working back to the original node.
    /* Check for null, in case someone passed in a null node, or
    they passed in an element that isn't rooted at root. */
    if(aNode == null) {
    if(depth == 0)
    return null;
    else
    retNodes = new TreeNode[depth];
    else {
    depth++;
    if(aNode == root)
    retNodes = new TreeNode[depth];
    else
    retNodes = getPathToRoot(aNode.getParent(), depth);
    retNodes[retNodes.length - depth] = aNode;
    return retNodes;
    // DynamicTreeTableModel.java END
    // IconRenderer.java BEGIN
    import java.awt.*;
    import javax.swing.*;
    import javax.swing.tree.*;
    import javax.swing.plaf.basic.BasicTreeUI;
    class IconRenderer extends DefaultTreeCellRenderer
    // Color backColor = new Color(0xD0, 0xCC, 0xFF);
    Color backColor = new Color(0xF0, 0xF0, 0xE0);
    String tipText = "";
    JTree tree;
    int currRow = 0;
    boolean m_selected;
    JTable table;
    public IconRenderer(JTree tree, JTable table) {
    this.table = table;
    // setBackground(backColor);
    setBackground(Color.GREEN);
    setForeground(Color.black);
         this.tree = tree;
    public Component getTreeCellRendererComponent(JTree tree, Object value,
    boolean selected,
    boolean expanded, boolean leaf,
    int row, boolean hasFocus) {
         Object node = null;
         super.getTreeCellRendererComponent(
    tree, value, selected,
    expanded, leaf, row,
    hasFocus);
         TreePath treePath = tree.getPathForRow(row);
    if(treePath != null)
              node = treePath.getLastPathComponent();
    currRow = row;
    m_selected = selected;
    DefaultMutableTreeNode itc = null;
    if (node instanceof DefaultMutableTreeNode) {
    itc = (DefaultMutableTreeNode)node;
         setClosedIcon(closedIcon);
    setOpenIcon(openIcon);
    return this;
    /* Override the default to send back different strings for folders and leaves. */
    public String getToolTipText() {
    return tipText;
    * Paints the value. The background is filled based on selected.
    public void paint(Graphics g) {
         super.paint(g);
         Color bColor = null;
         if(!m_selected) {
              System.out.println(" iconren not sel currRow " + currRow);
              if(currRow % 2 == 0) {
                   bColor = Color.WHITE;
              } else {
              bColor = backColor;
         } else {
              bColor = table.getSelectionBackground();
              System.out.println("in else selbg = " + bColor);           
              bColor = new Color(0xF0, 0xCC, 0x92);
              System.out.println(" bColor aft = " + bColor);           
         int imageOffset = -1;
         if(bColor != null) {
         imageOffset = getLabelStart();
         g.setColor(bColor);
         if(!m_selected) {
              System.out.println(" not sel setting white ");
              g.setXORMode(new Color(0xFF, 0xFF, 0xFF));
         } else {
    //          g.setXORMode(new Color(0xCC, 0xCC, 0x9F));
              g.setXORMode(new Color(0x00, 0x00, 0x00));
              System.out.println(" using color = " + g.getColor());           
         if(getComponentOrientation().isLeftToRight()) {
         g.fillRect(imageOffset, 0, getWidth() - 1 - imageOffset,
                   getHeight());
         } else {
         g.fillRect(0, 0, getWidth() - 1 - imageOffset,
                   getHeight());
    private int getLabelStart() {
         Icon currentI = getIcon();
         if(currentI != null && getText() != null) {
         return currentI.getIconWidth() + Math.max(0, getIconTextGap() - 1);
         return 0;
    // IconRenderer.java END
    // IndicatorRenderer.java BEGIN
    // import java.awt.*;
    import javax.swing.*;
    import javax.swing.border.*;
    import javax.swing.event.*;
    import javax.swing.tree.*;
    import javax.swing.table.*;
    import javax.swing.table.*;
    import javax.swing.plaf.basic.*;
    import java.awt.event.*;
    import java.util.EventObject;
    import java.text.NumberFormat;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.StringTokenizer;
    import java.util.Arrays;
    class IndicatorRenderer extends DefaultTableCellRenderer {
    /** Makes sure the number of displayed in an internationalized
    * manner. */
    protected NumberFormat formatter;
    /** Row that is currently being painted. */
    protected int lastRow;
    protected int reloadRow;
    protected int reloadCounter;
    protected TreeTableModel treeTableModel;
    protected TreeTableModelAdapter treeTblAdapter;
    protected JTable table;
    Component renderer = null;
    Color backColor = new Color(0xF0, 0xF0, 0xE0);
    IndicatorRenderer(TreeTableModelAdapter treeTblAdapter, TreeTableModel treeTableModel) {
         setHorizontalAlignment(JLabel.RIGHT);
         setFont(new Font("serif", Font.BOLD, 12));
         this.treeTableModel = treeTableModel;
         this.treeTblAdapter = treeTblAdapter;
    * Invoked as part of DefaultTableCellRenderers implemention. Sets
    * the text of the label.
    public void setValue(Object value) {
    /* setText((value == null) ? "---" : formatter.format(value)); */
         setText((value == null) ? "---" : (String) value.toString());
    * Returns this.
    public Component getTableCellRendererComponent(JTable table,
    Object value, boolean isSelected, boolean hasFocus,
    int row, int column) {
         renderer = super.getTableCellRendererComponent(table, value, isSelected,
    hasFocus, row, column);
         lastRow = row;
         this.table = table;
              if(isSelected) {
                   doMask(hasFocus, isSelected);
              } else
              setBackground(table.getBackground());
    return renderer;
    * If the row being painted is also being reloaded this will draw
    * a little indicator.
    public void paint(Graphics g) {
         super.paint(g);
    private void doMask(boolean hasFocus, boolean selected) {
              maskBackground(hasFocus, selected);
    private void maskBackground(boolean hasFocus, boolean selected) {
              Color seed = null;
              seed = table.getSelectionBackground();
              Color color = seed;
              if (color != null) {
                   setBackground(
    new Color(0xF0, 0xCC, 0x92));
    // IndicatorRenderer.java END
    // JTreeTable.java BEGIN
    import java.awt.*;
    import javax.swing.*;
    import javax.swing.border.*;
    import javax.swing.event.*;
    import javax.swing.tree.*;
    import javax.swing.table.*;
    import java.awt.event.*;
    import java.util.EventObject;
    public class JTreeTable extends JTable {
    /** A subclass of JTree. */
    protected TreeTableCellRenderer tree;
    protected IndicatorRenderer indicatorRenderer = null;
    public JTreeTable(TreeTableModel treeTableModel) {
         super();
         // Creates the tree. It will be used as a renderer and editor.
         tree = new TreeTableCellRenderer(treeTableModel);
         TreeTableModelAdapter tdap = new TreeTableModelAdapter(treeTableModel, tree);
         // Installs a tableModel representing the visible rows in the tree.
         super.setModel(tdap);
         // Forces the JTable and JTree to share their row selection models.
         ListToTreeSelectionModelWrapper selectionWrapper = new
         ListToTreeSelectionModelWrapper();
         tree.setSelectionModel(selectionWrapper);
         setSelectionModel(selectionWrapper.getListSelectionModel());
         // Installs the tree editor renderer and editor.
         setDefaultRenderer(TreeTableModel.class, tree);
         setDefaultEditor(TreeTableModel.class, new TreeTableCellEditor());
         indicatorRenderer = new IndicatorRenderer(tdap, treeTableModel);     
         // No grid.
         setShowGrid(false);
         // No intercell spacing
         setIntercellSpacing(new Dimension(0, 0));     
         // And update the height of the trees row to match that of
         // the table.
         //if (tree.getRowHeight() < 1) {
         // Metal looks better like this.
         setRowHeight(20);
    public TableCellRenderer getCellRenderer(int row, int col) {
              if(col == 0)
              return tree;
              else
              return indicatorRenderer;     
    public void updateUI() {
         super.updateUI();
         if(tree != null) {
         tree.updateUI();
         // Do this so that the editor is referencing the current renderer
         // from the tree. The renderer can potentially change each time
         // laf changes.
         setDefaultEditor(TreeTableModel.class, new TreeTableCellEditor());
         // Use the tree's default foreground and background colors in the
         // table.
    LookAndFeel.installColorsAndFont(this, "Tree.background",
    "Tree.foreground", "Tree.font");
    public int getEditingRow() {
    return (getColumnClass(editingColumn) == TreeTableModel.class) ? -1 :
         editingRow;
    private int realEditingRow() {
         return editingRow;
    public void sizeColumnsToFit(int resizingColumn) {
         super.sizeColumnsToFit(resizingColumn);
         if (getEditingColumn() != -1 && getColumnClass(editingColumn) ==
         TreeTableModel.class) {
         Rectangle cellRect = getCellRect(realEditingRow(),
                             getEditingColumn(), false);
    Component component = getEditorComponent();
         component.setBounds(cellRect);
    component.validate();
    public void setRowHeight(int rowHeight) {
    super.setRowHeight(rowHeight);
         if (tree != null && tree.getRowHeight() != rowHeight) {
    tree.setRowHeight(getRowHeight());
    public JTree getTree() {
         return tree;
    public boolean editCellAt(int row, int column, EventObject e){
         boolean retValue = super.editCellAt(row, column, e);
         if (retValue && getColumnClass(column) == TreeTableModel.class) {
         repaint(getCellRect(row, column, false));
         return retValue;
    public class TreeTableCellRenderer extends JTree implements
         TableCellRenderer {
         /** Last table/tree row asked to renderer. */
         protected int visibleRow;
         /** Border to draw around the tree, if this is non-null, it will
         * be painted. */
         protected Border highlightBorder;
         public TreeTableCellRenderer(Tr

  • Xml in JTree: how to not collpase JTree node, when renaming XML Node.

    Hi.
    I'm writing some kind of XML editor. I want to view my XML document in JTree and make user able to edit contents of XML. I made my own TreeModel for JTree, which straight accesses XML DOM, produced by Xerces. Using DOM Events, I made good-looking JTree updates without collapsing JTree on inserting or removing XML nodes.
    But there is a problem. I need to produce to user some method of renaming nodes. As I know, there is no way to rename node in w3c DOM. So I create new one with new name and copy all children and attributes to it. But in this way I got a new object of XML Node instead of renamed one. And I need to initiate rebuilding (treeStructureChanged event) of JTree structure. Renamed node collapses. If I use treeNodesChanged event (no rebuilding, just changes string view of JTree node), then when I try to operate with renamed node again, exception will be throwed.
    Is there some way to rename nodes in my program without collpasing JTree?
    I'am new to Java. Maybe there is a method in Xerces DOM implementation to rename nodes without recreating?
    Thanks in advance.

    I assume that "rename" means to change the element name? Anyway your question seems to be "When I add a node to a JTree, how do I make sure it is expanded?" This is completely concerned with Swing, so it might have been better to post it in the Swing forum, but if it were me I would do this:
    1. Copy the XML document into a JTree.
    2. Allow the user to edit the document. Don't attempt to keep an XML document or DOM synchronized with the contents of the JTree.
    3. On request of the user, copy the JTree back to a new XML document.
    This way you can "rename" things to the user's heart's content without having the problem you described.

  • Remove white space nodes from jtree

    I am trying to create jtree using XML DOM.
    But I m not able to remove/ignore the white space elements from DOM.
    I am getting output something like this
    for example
    Server
    Text
    node1
    Text
    I want something like this.
    Server
    node1
    I tried all option for removeing the white space
    Here I am posting the source
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.FactoryConfigurationError;
    import javax.xml.parsers.ParserConfigurationException;
    import org.xml.sax.SAXException;
    import org.xml.sax.SAXParseException;
    import java.io.File;
    import java.io.IOException;
    import org.w3c.dom.Document;
    import org.w3c.dom.DOMException;
    // Basic GUI components
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTree;
    // GUI components for right-hand side
    import javax.swing.JSplitPane;
    import javax.swing.JEditorPane;
    // GUI support classes
    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.Toolkit;
    import java.awt.event.WindowEvent;
    import java.awt.event.WindowAdapter;
    // For creating borders
    import javax.swing.border.EmptyBorder;
    import javax.swing.border.BevelBorder;
    import javax.swing.border.CompoundBorder;
    // For creating a TreeModel
    import javax.swing.tree.*;
    import javax.swing.event.*;
    import java.util.*;
    public class DomEcho02 extends JPanel
    // Global value so it can be ref'd by the tree-adapter
    static Document document;
    static final int windowHeight = 460;
    static final int leftWidth = 300;
    static final int rightWidth = 340;
    static final int windowWidth = leftWidth + rightWidth;
    public DomEcho02()
    // Make a nice border
    EmptyBorder eb = new EmptyBorder(5,5,5,5);
    BevelBorder bb = new BevelBorder(BevelBorder.LOWERED);
    CompoundBorder cb = new CompoundBorder(eb,bb);
    this.setBorder(new CompoundBorder(cb,eb));
    // Set up the tree
    JTree tree = new JTree(new DomToTreeModelAdapter());
    // Iterate over the tree and make nodes visible
    // (Otherwise, the tree shows up fully collapsed)
    //TreePath nodePath = ???;
    // tree.expandPath(nodePath);
    // Build left-side view
    JScrollPane treeView = new JScrollPane(tree);
    treeView.setPreferredSize(
    new Dimension( leftWidth, windowHeight ));
    // Build right-side view
    JEditorPane htmlPane = new JEditorPane("text/html","");
    htmlPane.setEditable(false);
    JScrollPane htmlView = new JScrollPane(htmlPane);
    htmlView.setPreferredSize(
    new Dimension( rightWidth, windowHeight ));
    // Build split-pane view
    JSplitPane splitPane =
    new JSplitPane( JSplitPane.HORIZONTAL_SPLIT,
    treeView,
    htmlView );
    splitPane.setContinuousLayout( true );
    splitPane.setDividerLocation( leftWidth );
    splitPane.setPreferredSize(
    new Dimension( windowWidth + 10, windowHeight+10 ));
    // Add GUI components
    this.setLayout(new BorderLayout());
    this.add("Center", splitPane );
    } // constructor
    public static void main(String argv[])
    if (argv.length != 1) {
    System.err.println("Usage: java DomEcho filename");
    System.exit(1);
    DocumentBuilderFactory factory =
    DocumentBuilderFactory.newInstance();
    //factory.setValidating(true);
    //factory.setNamespaceAware(true);
    try {
    DocumentBuilder builder = factory.newDocumentBuilder();
    document = builder.parse( new File(argv[0]) );
    makeFrame();
    } catch (SAXException sxe) {
    // Error generated during parsing)
    Exception x = sxe;
    if (sxe.getException() != null)
    x = sxe.getException();
    x.printStackTrace();
    } catch (ParserConfigurationException pce) {
    // Parser with specified options can't be built
    pce.printStackTrace();
    } catch (IOException ioe) {
    // I/O error
    ioe.printStackTrace();
    } // main
    public static void makeFrame() {
    // Set up a GUI framework
    JFrame frame = new JFrame("DOM Echo");
    frame.addWindowListener(
    new WindowAdapter() {
    public void windowClosing(WindowEvent e) {System.exit(0);}
    // Set up the tree, the views, and display it all
    final DomEcho02 echoPanel =
    new DomEcho02();
    frame.getContentPane().add("Center", echoPanel );
    frame.pack();
    Dimension screenSize =
    Toolkit.getDefaultToolkit().getScreenSize();
    int w = windowWidth + 10;
    int h = windowHeight + 10;
    frame.setLocation(screenSize.width/3 - w/2,
    screenSize.height/2 - h/2);
    frame.setSize(w, h);
    frame.setVisible(true);
    } // makeFrame
    // An array of names for DOM node-types
    // (Array indexes = nodeType() values.)
    static final String[] typeName = {
    "none",
    "Element",
    "Attr",
    "Text",
    "CDATA",
    "EntityRef",
    "Entity",
    "ProcInstr",
    "Comment",
    "Document",
    "DocType",
    "DocFragment",
    "Notation",
    // This class wraps a DOM node and returns the text we want to
    // display in the tree. It also returns children, index values,
    // and child counts.
    public class AdapterNode
    org.w3c.dom.Node domNode;
    // Construct an Adapter node from a DOM node
    public AdapterNode(org.w3c.dom.Node node) {
    domNode = node;
    // Return a string that identifies this node in the tree
    // *** Refer to table at top of org.w3c.dom.Node ***
    public String toString() {
    String s = typeName[domNode.getNodeType()];
    String nodeName = domNode.getNodeName();
    if (! nodeName.startsWith("#")) {
    s += ": " + nodeName;
    if (domNode.getNodeValue() != null) {
    if (s.startsWith("ProcInstr"))
    s += ", ";
    else
    s += ": ";
    // Trim the value to get rid of NL's at the front
    String t = domNode.getNodeValue().trim();
    int x = t.indexOf("\n");
    if (x >= 0) t = t.substring(0, x);
    s += t;
    return s;
    * Return children, index, and count values
    public int index(AdapterNode child) {
    //System.err.println("Looking for index of " + child);
    int count = childCount();
    for (int i=0; i<count; i++) {
    AdapterNode n = this.child(i);
    if (child.domNode == n.domNode) return i;
    return -1; // Should never get here.
    public AdapterNode child(int searchIndex) {
    //Note: JTree index is zero-based.
    org.w3c.dom.Node node =
    domNode.getChildNodes().item(searchIndex);
    return new AdapterNode(node);
    public int childCount() {
    return domNode.getChildNodes().getLength();
    // This adapter converts the current Document (a DOM) into
    // a JTree model.
    public class DomToTreeModelAdapter
    implements javax.swing.tree.TreeModel
    // Basic TreeModel operations
    public Object getRoot() {
    //System.err.println("Returning root: " +document);
    return new AdapterNode(document);
    public boolean isLeaf(Object aNode) {
    // Determines whether the icon shows up to the left.
    // Return true for any node with no children
    AdapterNode node = (AdapterNode) aNode;
    if (node.childCount() > 0) return false;
    return true;
    public int getChildCount(Object parent) {
    AdapterNode node = (AdapterNode) parent;
    return node.childCount();
    public Object getChild(Object parent, int index) {
    AdapterNode node = (AdapterNode) parent;
    return node.child(index);
    public int getIndexOfChild(Object parent, Object child) {
    AdapterNode node = (AdapterNode) parent;
    return node.index((AdapterNode) child);
    public void valueForPathChanged(TreePath path, Object newValue) {
    // Null. We won't be making changes in the GUI
    // If we did, we would ensure the new value was really new,
    // adjust the model, and then fire a TreeNodesChanged event.
    * Use these methods to add and remove event listeners.
    * (Needed to satisfy TreeModel interface, but not used.)
    private Vector listenerList = new Vector();
    public void addTreeModelListener(TreeModelListener listener) {
    if ( listener != null
    && ! listenerList.contains( listener ) ) {
    listenerList.addElement( listener );
    public void removeTreeModelListener(TreeModelListener listener) {
    if ( listener != null ) {
    listenerList.removeElement( listener );
    // Note: Since XML works with 1.1, this example uses Vector.
    // If coding for 1.2 or later, though, I'd use this instead:
    // private List listenerList = new LinkedList();
    // The operations on the List are then add(), remove() and
    // iteration, via:
    // Iterator it = listenerList.iterator();
    // while ( it.hasNext() ) {
    // TreeModelListener listener = (TreeModelListener) it.next();
    * Invoke these methods to inform listeners of changes.
    * (Not needed for this example.)
    * Methods taken from TreeModelSupport class described at
    * http://java.sun.com/products/jfc/tsc/articles/jtree/index.html
    * That architecture (produced by Tom Santos and Steve Wilson)
    * is more elegant. I just hacked 'em in here so they are
    * immediately at hand.
    public void fireTreeNodesChanged( TreeModelEvent e ) {
    Enumeration listeners = listenerList.elements();
    while ( listeners.hasMoreElements() ) {
    TreeModelListener listener =
    (TreeModelListener) listeners.nextElement();
    listener.treeNodesChanged( e );
    public void fireTreeNodesInserted( TreeModelEvent e ) {
    Enumeration listeners = listenerList.elements();
    while ( listeners.hasMoreElements() ) {
    TreeModelListener listener =
    (TreeModelListener) listeners.nextElement();
    listener.treeNodesInserted( e );
    public void fireTreeNodesRemoved( TreeModelEvent e ) {
    Enumeration listeners = listenerList.elements();
    while ( listeners.hasMoreElements() ) {
    TreeModelListener listener =
    (TreeModelListener) listeners.nextElement();
    listener.treeNodesRemoved( e );
    public void fireTreeStructureChanged( TreeModelEvent e ) {
    Enumeration listeners = listenerList.elements();
    while ( listeners.hasMoreElements() ) {
    TreeModelListener listener =
    (TreeModelListener) listeners.nextElement();
    listener.treeStructureChanged( e );
    }

    DocumentBuilderFactory can be configured to ignore white space.
    http://java.sun.com/j2se/1.5.0/docs/api/javax/xml/parsers/DocumentBuilderFactory.html#setIgnoringElementContentWhitespace(boolean)

  • Help with displaying a JTree

    Hi,
    I have developed a webspider that cycles through a website detecting all urls and checking for borken links. I currently have build a JTree that takes the current url that is being processed and creates a string and adds it to a JTree. The problem I have is that the urls are printed in the JTree as one long list, e.g.
    |Test
    |____url 1
    |____url 1a
    |____url 2
    |____url 2a
    I would like it to disply like this:
    |Test
    |____url 1
    |-------|____url 1a
    |____url 2
    |-------|____url 2a
    (I have had to place the dashes in so it displays properly)
    So that the strucutre of the website can be seen. I have read the JTree tutroial and my code looks like this, sorry its large i'm not too sure which bits to cut out:
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.tree.*;
    import javax.swing.event.*;
    import java.net.*;
    import java.io.*;
    import java.util.*;
    public class gui extends JFrame implements Runnable
          *declare variable, boolean
          *thread, a object and a center
          *pane
         protected URL urlInput;
         protected Thread bgThread;
         protected boolean run = false;
         protected WebSpider webSpider;
         public String brokenUrl;
         public String goodUrl;
         public String deadUrl;
         protected DefaultMutableTreeNode rootNode;
        protected DefaultTreeModel treeModel;
         public gui()
                *create the gui here
               setTitle("Testing Tool");
             setSize(600,600);
             //add Buttons to the tool bar
             start.setText("Start");
             start.setActionCommand("Start");
             toolBar.add(start);
             ButtonListener startListener = new ButtonListener();
                 start.addActionListener(startListener);
              cancel.setText("Cancel");
             cancel.setActionCommand("Cancel");
             toolBar.add(cancel);
             ButtonListener cancelListener = new ButtonListener();
                 cancel.addActionListener(cancelListener);
                 clear.setText("Clear");
             clear.setActionCommand("Clear");
             toolBar.add(clear);
             ButtonListener clearListener = new ButtonListener();
                 clear.addActionListener(clearListener);
                 close.setText("Close");
             close.setActionCommand("Close");
             toolBar.add(close);
             ButtonListener closeListener = new ButtonListener();
                 close.addActionListener(closeListener);
                 //creat a simple form
                 urlLabel.setText("Enter URL:");
                 urlLabel.setBounds(100,36,288,24);
                 formTab.add(urlLabel);
                 url.setBounds(170,36,288,24);
                 formTab.add(url);
                 current.setText("Currently Processing: ");
                 current.setBounds(100,80,288,24);
                 formTab.add(current);
             //add the scrol pane and text area to the error tab
             errorTab.add(errorPane);
             errorPane.setBounds(0,0,580,490);
             errorPane.getViewport().add(errorText);
             //add the scroll pane to the tree tab
             treeTab.add(treePane);
             treePane.setBounds(0,0,580,490);
             //create the JTree
             rootNode = new DefaultMutableTreeNode("Test");
             treeModel = new DefaultTreeModel(rootNode);
             treeModel.addTreeModelListener(new MyTreeModelListener());
             tree = new JTree(treeModel);
             tree.setEditable(true);
             tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
            tree.setShowsRootHandles(true);
             treePane.getViewport().add(tree);
             //create the tabbed window             
            centerPane.setBorder(new javax.swing.border.EtchedBorder());
            formTab.setLayout(null);
            errorTab.setLayout(null);
            treeTab.setLayout(null);
            centerPane.addTab("Search Parameters", formTab);
            centerPane.addTab("Error Messages", errorTab);
            centerPane.addTab("Website Structure", treeTab);
              //add the tool bar and tabbed pane
              getContentPane().add(toolBar, java.awt.BorderLayout.NORTH);
            getContentPane().add(centerPane, java.awt.BorderLayout.CENTER);             
                 *create the tool bar pane, a center pane, add the buttons,
                 *labels, tabs, a text field for user input here
                javax.swing.JPanel toolBar = new javax.swing.JPanel();
                javax.swing.JButton start = new javax.swing.JButton();
              javax.swing.JButton cancel = new javax.swing.JButton();
              javax.swing.JButton clear = new javax.swing.JButton();
              javax.swing.JButton close = new javax.swing.JButton();      
                javax.swing.JTabbedPane centerPane = new javax.swing.JTabbedPane();
                javax.swing.JPanel formTab = new javax.swing.JPanel();
                javax.swing.JLabel urlLabel = new javax.swing.JLabel();
                javax.swing.JLabel current = new javax.swing.JLabel();
                javax.swing.JTextField url = new javax.swing.JTextField();
                javax.swing.JPanel errorTab = new javax.swing.JPanel();
                javax.swing.JTextArea errorText = new javax.swing.JTextArea();
                javax.swing.JScrollPane errorPane = new javax.swing.JScrollPane();
                javax.swing.JPanel treeTab = new javax.swing.JPanel();
                javax.swing.JScrollPane treePane = new javax.swing.JScrollPane();
                javax.swing.JTree tree = new javax.swing.JTree();
               *show the gui
              public static void main(String args[])
                  (new gui()).setVisible(true);
              *listen for the button presses and set the
              *boolean flag depending on which button is pressed
             class ButtonListener implements ActionListener
                  public void actionPerformed(ActionEvent event)
                       Object object = event.getSource();
                       if (object == start)
                            run = true;
                            startActionPerformed(event);
                       if (object == cancel)
                            run = false;
                            startActionPerformed(event);
                       if (object == clear)
                            errorText.setText("");
                            rootNode.removeAllChildren();
                           treeModel.reload();
                       if (object == close)
                            System.exit(0);
              *this method is called when the start or
              *cancel button is pressed.
             void startActionPerformed (ActionEvent event)
                  if (run == true && bgThread == null)
                       bgThread = new Thread(this);
                       bgThread.start();
                  if (run == false && bgThread != null)
                       webSpider.cancel();
              *this mehtod will start the background thred.
              *the background thread is required so that the
              *GUI is still displayed
             public void run()
                  try
                           webSpider = new WebSpider(this);
                         webSpider.clear();
                         urlInput = new URL(url.getText());
                       webSpider.addURL(urlInput);
                       webSpider.run();
                       bgThread = null;
                      catch (MalformedURLException e)
                           addressError addErr = new addressError();
                         addErr.addMsg = "URL ERROR - PLEASE CHECK";
                         SwingUtilities.invokeLater(addErr);
                 *this method is called by the web spider
                 *once a url is found. Validation of navigation
                 *happens here.
                public boolean urlFound(URL urlInput,URL url)
                      CurrentlyProcessing pro = new CurrentlyProcessing();
                  pro.msg = url.toString();
                  SwingUtilities.invokeLater(pro);
                  if (!testLink(url))
                        navigationError navErr = new navigationError();
                        navErr.navMsg = "Broken Link "+url+" caused on "+urlInput+"\n";
                        brokenUrl = url.toString();
                        return false;
                  if (!url.getHost().equalsIgnoreCase(urlInput.getHost()))
                        return false;
                  else
                         return true;
                //this method is returned if there is no link on a web page
                public void urlNotFound(URL urlInput)
                          deadEnd dEnd = new deadEnd();
                           dEnd.dEMsg = "No links on "+urlInput+"\n";
                           deadUrl = urlInput.toString();                
                //this method is called internally to check that a link works              
                protected boolean testLink(URL url)
                   try
                         URLConnection connection = url.openConnection();
                         connection.connect();
                         goodUrl = url.toString();
                         return true;
                  catch (IOException e)
                         return false;
                //this method is called when an error is found            
                public void urlError(URL url)
              //this method is called when an email address is found             
                public void emailFound(String email)
              //this method will update any navigation errors found
              class addressError implements Runnable
                   public String addMsg;
                   public void run()
                        current.setText("Currently Processing: "+ addMsg);
                        errorText.append(addMsg);
              class navigationError implements Runnable
                   public String navMsg;
                   public void run()
                        errorText.append(navMsg);
              class deadEnd implements Runnable
                   public String dEMsg;
                   public void run()
                        errorText.append(dEMsg);
              //this method will update the currently processing field on the GUI
              public class CurrentlyProcessing implements Runnable
                   public String msg;
                  //public String msgInfo = msg;
                     public void run()
                         current.setText("Currently Processing: " + msg );
                         addObject(msg);
             //add a node to the tree
                public DefaultMutableTreeNode addObject (Object child)
                 DefaultMutableTreeNode parentNode = null;
                 return addObject(parentNode, child, true);
             public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent,Object child,boolean shouldBeVisible)
                 DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(child);
                 if (parent == null)
                     parent = rootNode;
                 treeModel.insertNodeInto(childNode, parent, parent.getChildCount());
                 if (shouldBeVisible)
                     tree.scrollPathToVisible(new TreePath(childNode.getPath()));
                      return childNode;
             //listener for the tree model     
             public class MyTreeModelListener implements TreeModelListener
                  public void treeNodesChanged (TreeModelEvent e)
                       DefaultMutableTreeNode node;
                       node = (DefaultMutableTreeNode)
                       (e.getTreePath().getLastPathComponent());
                       try
                            int index = e.getChildIndices()[0];
                            node = (DefaultMutableTreeNode)
                            (node.getChildAt(index));
                       catch (NullPointerException exc)
                  public void treeNodesInserted(TreeModelEvent e)
                  public void treeStructureChanged(TreeModelEvent e)
                  public void treeNodesRemoved(TreeModelEvent e)
    }It uses a class called webspider which i have not attached, if required please let me know. I beleive that in addObject I am adding all nodes to the root as children.
    Any help would be much appreciated.
    Many Thanks
    MRv

    I would recomend you create your own JTree class for this.
    Here are a few things I set in my constructor within the JTree:
    // turn on tooltips
    ToolTipManager.sharedInstance().registerComponent(this);
    // used by two setters so create reference
    RollupTreeCellRenderer renderer = new RollupTreeCellRenderer();
    // customizing the icons for the tree
    // setting the folder icons
    renderer.setOpenIcon(IconLoader.getIcon("Open.gif"));
    renderer.setClosedIcon(IconLoader.getIcon("Folder.gif"));
    // inventory icon
    renderer.setLeafIcon(IconLoader.getIcon("Document.gif"));
    // add renderer to highlight Inventory nodes with Red or Blue text
    setCellRenderer(renderer);
    Here is the renderer class example:
    class RollupTreeCellRenderer
    extends DefaultTreeCellRenderer
    * Configures the renderer based on the passed in components.
    * The value is set from messaging the tree with
    * <code>convertValueToText</code>, which ultimately invokes
    * <code>toString</code> on <code>value</code>.
    * The foreground color is set based on the selection and the icon
    * is set based on on leaf and expanded.
    * @param tree JTree
    * @param value Object
    * @param sel boolean
    * @param expanded boolean
    * @param leaf boolean
    * @param row int
    * @param hasFocus boolean
    * @return Component
    public Component getTreeCellRendererComponent(JTree tree, Object value,
    boolean sel,
    boolean expanded,
    boolean leaf, int row,
    boolean hasFocus)
    // call super for default behavior
    super.getTreeCellRendererComponent(tree,
    value,
    sel,
    expanded,
    leaf,
    row,
    hasFocus);
    // if the current node is selected do NOT over-ride
    // the default colors
    if (sel)
    return this;
    // cast to our wrapper Node class
    RollupNode node = (RollupNode) value;
    if (node.isInventory())
    if (RollupMediator.getInstance().nodeInList(node))
    setForeground(RollupTree.FOUND);
    setToolTipText("Click to find positions count");
    else
    setForeground(RollupTree.NOT_FOUND);
    setToolTipText("Inventory not in current business date");
    else
    setToolTipText("Double click to edit name");
    return this;
    } // Renderer
    Let me know if you need more examples.
    BTW
    I the TreeCellRenderer example is not public so I can add it to the bottom of the file that contains my custom JTree.

  • JTree with XML content expand/collapse problem

    Hello all,
    I'm having this very weird problem with a JTree I use to display the contents of an XML file. I use the DOM parser (and not JDOM since I want the application to run as an applet as well, and don't want to have any external libraries for the user to download) and have a custom TreeModel and TreeNode implementations to wrap the DOM nodes so that they are displayed by the JTree.
    I have also added a popup menu in the tree, for the user to be able to expand/collapse all nodes under the selected one (i.e. a recursive method).
    When expandAll is run, everything works fine and the children of the selected node are expanded (and their children and so on).
    However, after the expansion when I run the collapseAll function, even though the selected node collapses, when I re-expand it (manually not by expandAll) all of it's children are still fully open! Even if I collapse sub-elements of the node manually and then collapse this node and re-expand it, it "forgets" the state of it's children and shows them fully expanded.
    In other words once I use expandAll no matter what I do, the children of this node will be expanded (once I close it and re-open it).
    Also after running expandAll the behaviour(!) of the expanded nodes change: i have tree.setToggleClickCount(1); but on the expanded nodes I need to double-click to collapse them.
    I believe the problem is related to my implementations of TreeModel and TreeNode but after many-many hours of trying to figure out what's happening I'm desperate... Please help!
    Here's my code:
    public class XMLTreeNode implements TreeNode 
         //This class wraps a DOM node
        org.w3c.dom.Node domNode;
        protected boolean allowChildren;
        protected Vector children;
        //compressed view (#text).
         private static boolean compress = true;   
        // An array of names for DOM node-types
        // (Array indexes = nodeType() values.)
        static final String[] typeName = {
            "none",
            "Element",
            "Attr",
            "Text",
            "CDATA",
            "EntityRef",
            "Entity",
            "ProcInstr",
            "Comment",
            "Document",
            "DocType",
            "DocFragment",
            "Notation",
        static final int ELEMENT_TYPE =   1;
        static final int ATTR_TYPE =      2;
        static final int TEXT_TYPE =      3;
        static final int CDATA_TYPE =     4;
        static final int ENTITYREF_TYPE = 5;
        static final int ENTITY_TYPE =    6;
        static final int PROCINSTR_TYPE = 7;
        static final int COMMENT_TYPE =   8;
        static final int DOCUMENT_TYPE =  9;
        static final int DOCTYPE_TYPE =  10;
        static final int DOCFRAG_TYPE =  11;
        static final int NOTATION_TYPE = 12;
        // The list of elements to display in the tree
       static String[] treeElementNames = {
            "node",
      // Construct an Adapter node from a DOM node
      public XMLTreeNode(org.w3c.dom.Node node) {
        domNode = node;
      public String toString(){
           if (domNode.hasAttributes()){
                return domNode.getAttributes().getNamedItem("label").getNodeValue();
           }else return domNode.getNodeName();      
      public boolean isLeaf(){ 
           return (this.getChildCount()==0);
      boolean treeElement(String elementName) {
          for (int i=0; i<treeElementNames.length; i++) {
            if ( elementName.equals(treeElementNames)) return true;
    return false;
    public int getChildCount() {
         if (!compress) {   
    return domNode.getChildNodes().getLength();
    int count = 0;
    for (int i=0; i<domNode.getChildNodes().getLength(); i++) {
    org.w3c.dom.Node node = domNode.getChildNodes().item(i);
    if (node.getNodeType() == ELEMENT_TYPE
    && treeElement( node.getNodeName() ))
    // Note:
    // Have to check for proper type.
    // The DOCTYPE element also has the right name
    ++count;
    return count;
    public boolean getAllowsChildren() {
         // TODO Auto-generated method stub
         return true;
    public Enumeration children() {
         // TODO Auto-generated method stub
         return null;
    public TreeNode getParent() {
         // TODO Auto-generated method stub
         return null;
    public TreeNode getChildAt(int searchIndex) {
    org.w3c.dom.Node node =
    domNode.getChildNodes().item(searchIndex);
    if (compress) {
    // Return Nth displayable node
    int elementNodeIndex = 0;
    for (int i=0; i<domNode.getChildNodes().getLength(); i++) {
    node = domNode.getChildNodes().item(i);
    if (node.getNodeType() == ELEMENT_TYPE
    && treeElement( node.getNodeName() )
    && elementNodeIndex++ == searchIndex) {
    break;
    return new XMLTreeNode(node);
    public int getIndex(TreeNode tnode) {
         if (tnode== null) {
              throw new IllegalArgumentException("argument is null");
         XMLTreeNode child=(XMLTreeNode)tnode;
         int count = getChildCount();
         for (int i=0; i<count; i++) {
              XMLTreeNode n = (XMLTreeNode)this.getChildAt(i);
              if (child.domNode == n.domNode) return i;
         return -1; // Should never get here.
    public class XMLTreeModel2 extends DefaultTreeModel
         private Vector listenerList = new Vector();
         * This adapter converts the current Document (a DOM) into
         * a JTree model.
         private Document document;
         public XMLTreeModel2 (Document doc){
              super(new XMLTreeNode(doc));
              this.document=doc;
         public Object getRoot() {
              //System.err.println("Returning root: " +document);
              return new XMLTreeNode(document);
         public boolean isLeaf(Object aNode) {
              return ((XMLTreeNode)aNode).isLeaf();
         public int getChildCount(Object parent) {
              XMLTreeNode node = (XMLTreeNode) parent;
    return node.getChildCount();
         public Object getChild(Object parent, int index) {
    XMLTreeNode node = (XMLTreeNode) parent;
    return node.getChildAt(index);
         public int getIndexOfChild(Object parent, Object child) {
    if (parent==null || child==null )
         return -1;
              XMLTreeNode node = (XMLTreeNode) parent;
    return node.getIndex((XMLTreeNode) child);
         public void valueForPathChanged(TreePath path, Object newValue) {
    // Null. no changes
         public void addTreeModelListener(TreeModelListener listener) {
              if ( listener != null
    && ! listenerList.contains( listener ) ) {
    listenerList.addElement( listener );
         public void removeTreeModelListener(TreeModelListener listener) {
              if ( listener != null ) {
    listenerList.removeElement( listener );
         public void fireTreeNodesChanged( TreeModelEvent e ) {
    Enumeration listeners = listenerList.elements();
    while ( listeners.hasMoreElements() ) {
    TreeModelListener listener =
    (TreeModelListener) listeners.nextElement();
    listener.treeNodesChanged( e );
         public void fireTreeNodesInserted( TreeModelEvent e ) {
    Enumeration listeners = listenerList.elements();
    while ( listeners.hasMoreElements() ) {
    TreeModelListener listener =
    (TreeModelListener) listeners.nextElement();
    listener.treeNodesInserted( e );
         public void fireTreeNodesRemoved( TreeModelEvent e ) {
    Enumeration listeners = listenerList.elements();
    while ( listeners.hasMoreElements() ) {
    TreeModelListener listener =
    (TreeModelListener) listeners.nextElement();
    listener.treeNodesRemoved( e );
         public void fireTreeStructureChanged( TreeModelEvent e ) {
    Enumeration listeners = listenerList.elements();
    while ( listeners.hasMoreElements() ) {
    TreeModelListener listener =
    (TreeModelListener) listeners.nextElement();
    listener.treeStructureChanged( e );
    The collapseAll, expandAll code (even though I m pretty sure that's not the problem since they work fine on a normal JTree):
        private void collapseAll(TreePath tp){
             if (tp==null) return;
             Object node=tp.getLastPathComponent();
             TreeModel model=tree.getModel();
             if (!model.isLeaf(node)){
                  tree.collapsePath(tp);
                  for (int i=0;i<model.getChildCount(node);i++){
                  //for (int i = node.childCount()-4;i>=0;i--){
                       collapseAll(tp.pathByAddingChild(model.getChild(node,i)));
                  tree.collapsePath(tp);
        private void expandAll(TreePath tp){
             if (tp==null) return;
             Object node=tp.getLastPathComponent();
             TreeModel model=tree.getModel();
             if (!model.isLeaf(node)){
                  tree.expandPath(tp);
                  for (int i=0;i<model.getChildCount(node);i++){
                  //for (int i = node.childCount()-4;i>=0;i--){
                       expandAll(tp.pathByAddingChild(model.getChild(node,i)));

    Hi,
    Iam not facing this problem. To CollapseAll, I do a tree.getModel().reload() which causes all nodes to get collapsed and remain so even if I reopen them manually.
    Hope this helps.
    cheers,
    vidyut

  • JTree with XML Content

    Hi Friends,
    I am trying to create a JTree whose data will come from a XML Document. Whenever the tree is refreshed (There is a JPopupMenu on the tree which allows the user to call refresh), the tree must update itself with the underlying XML document. If there is any change in the xml doc, it must be reflected in the tree. However, the tree must not collapse when the refresh is called. For example if I have a tree like this:-
    + Root
        |
        ------ Child #1
        |            |
        |            -------- A
        |            |
        |            -------- B
        |
        +------ Child #2
        |
        ------- Child #3
                    |
                    -------- AAA
                    |
                    -------- BBBThe XML Document for the above tree structure would be:-
    <?xml version="1.0" encoding="UTF-8"?>
    <Root>Root
          <Child> Child #1
                <SubChild>A</SubChild>
                <SubChild>B</SubChild>
          </Child>
          <Child> Child #2
                <SubChild>AA</SubChild>
                <SubChild>BB</SubChild>
          </Child>
          <Child> Child #3
                <SubChild>AAA</SubChild>
                <SubChild>BBB</SubChild>
          </Child>
    </Root>Now if i add another node (CCC) in Child #3 (by adding another Subchild element in the XML document), and click refresh on the tree, the tree should look like:-
    + Root
        |
        ------ Child #1
        |            |
        |            -------- A
        |            |
        |            -------- B
        |
        +------ Child #2
        |
        ------- Child #3
                    |
                    -------- AAA
                    |
                    -------- BBB
                    |
                    -------- CCCHowever, if i am trying to reload the tree model, after reading the XML file, the whole tree collapses.
    Can anyone please help me out with this problem?
    Thanx a lot in advance,
    ~Debopam

    * XMLNode.java
    * Created on December 18, 2004, 4:25 PM
    package debopam.utils.xml;
    import java.util.Enumeration;
    import java.util.NoSuchElementException;
    import java.util.Vector;
    import javax.swing.tree.MutableTreeNode;
    import javax.swing.tree.TreeNode;
    import org.jdom.Element;
    * @author Debopam Ghoshal
    public class XMLNode implements MutableTreeNode
        private Element nodeElement;
        private XMLNode parent;
        /** optional user object */
        transient protected Object     userObject;
        /** true if the node is able to have children */
        protected boolean allowsChildren;
        /** array of children, may be null if this node has no children */
        protected Vector children;
         * An enumeration that is always empty. This is used when an enumeration
         * of a leaf node's children is requested.
        static public final Enumeration<TreeNode> EMPTY_ENUMERATION
                = new Enumeration<TreeNode>()
            public boolean hasMoreElements()
            { return false; }
            public TreeNode nextElement()
                throw new NoSuchElementException("No more elements");
        /** Creates a new instance of XMLNode */
        public XMLNode(Element nodeElement, boolean allowsChildren)
            this.nodeElement = nodeElement;
            this.allowsChildren = allowsChildren;
        public XMLNode(String nodeName, boolean allowsChildren)
            nodeElement = new Element(nodeName);
            this.allowsChildren = allowsChildren;
         * Creates and returns a forward-order enumeration of this node's
         * children.  Modifying this node's child array invalidates any child
         * enumerations created before the modification.
         * @return     an Enumeration of this node's children
        public java.util.Enumeration children()
            if(children == null)
                return EMPTY_ENUMERATION;
            else
                return children.elements();
         * Returns true if this node is allowed to have children.
         * @return     true if this node allows children, else false
        public boolean getAllowsChildren()
            return allowsChildren;
         * 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
        public void setAllowsChildren(boolean allows)
            if (allows != allowsChildren)
                allowsChildren = allows;
                if (!allowsChildren)
                    removeAllChildren();
         * Returns the child at the specified index in this node's child array.
         * @param     index     an index into this node's child array
         * @exception     ArrayIndexOutOfBoundsException     if <code>index</code>
         *                              is out of bounds
         * @return     the TreeNode in this node's child array at  the specified index
        public javax.swing.tree.TreeNode getChildAt(int index)
            if (children == null)
                throw new ArrayIndexOutOfBoundsException("node has no children");
            return (TreeNode)children.elementAt(index);
         * Returns the number of children of this node.
         * @return     an int giving the number of children of this node
        public int getChildCount()
            if (children == null)
                return 0;
            else
                return children.size();
         * Returns the index of the specified child in this node's child array.
         * If the specified node is not a child of this node, returns
         * <code>-1</code>.  This method performs a linear search and is O(n)
         * where n is the number of children.
         * @param     aChild     the TreeNode to search for among this node's children
         * @exception     IllegalArgumentException     if <code>aChild</code>
         *                                   is null
         * @return     an int giving the index of the node in this node's child
         *          array, or <code>-1</code> if the specified node is a not
         *          a child of this node
        public int getIndex(TreeNode aChild)
            if (aChild == null)
                throw new IllegalArgumentException("argument is null");
            if (!isNodeChild(aChild))
                return -1;
            return children.indexOf(aChild);     // linear search
         * Returns this node's parent or null if this node has no parent.
         * @return     this node's parent TreeNode, or null if this node has no parent
        public TreeNode getParent()
            return parent;
         * Removes <code>newChild</code> from its present parent (if it has a
         * parent), sets the child's parent to this node, and then adds the child
         * to this node's child array at index <code>childIndex</code>.
         * <code>newChild</code> must not be null and must not be an ancestor of
         * this node.
         * @param     newChild     the MutableTreeNode to insert under this node
         * @param     childIndex     the index in this node's child array
         *                    where this node is to be inserted
         * @exception     ArrayIndexOutOfBoundsException     if
         *                    <code>childIndex</code> is out of bounds
         * @exception     IllegalArgumentException     if
         *                    <code>newChild</code> is null or is an
         *                    ancestor of this node
         * @exception     IllegalStateException     if this node does not allow
         *                              children
         * @see     #isNodeDescendant
        public void insert(MutableTreeNode newChild, int childIndex)
            if (!allowsChildren)
                throw new IllegalStateException("node does not allow children");
            else if (newChild == null)
                throw new IllegalArgumentException("new child is null");
            else if (isNodeAncestor(newChild))
                throw new IllegalArgumentException("new child is an ancestor");
            MutableTreeNode oldParent = (MutableTreeNode)newChild.getParent();
            if (oldParent != null)
                oldParent.remove(newChild);
            newChild.setParent(this);
            if (children == null)
                children = new Vector();
            children.insertElementAt(newChild, childIndex);
        public boolean isLeaf()
            return !nodeElement.hasChildren();
         * Removes the child at the specified index from this node's children
         * and sets that node's parent to null. The child node to remove
         * must be a <code>MutableTreeNode</code>.
         * @param     childIndex     the index in this node's child array
         *                    of the child to remove
         * @exception     ArrayIndexOutOfBoundsException     if
         *                    <code>childIndex</code> is out of bounds
        public void remove(int childIndex)
            MutableTreeNode child = (MutableTreeNode)getChildAt(childIndex);
            children.removeElementAt(childIndex);
            child.setParent(null);
         * Removes <code>aChild</code> from this node's child array, giving it a
         * null parent.
         * @param     aChild     a child of this node to remove
         * @exception     IllegalArgumentException     if <code>aChild</code>
         *                         is null or is not a child of this node
        public void remove(MutableTreeNode aChild)
            if (aChild == null)
                throw new IllegalArgumentException("argument is null");
            if (!isNodeChild(aChild))
                throw new IllegalArgumentException("argument is not a child");
            remove(getIndex(aChild));     // linear search
         * Removes the subtree rooted at this node from the tree, giving this
         * node a null parent.  Does nothing if this node is the root of its
         * tree.
        public void removeFromParent()
            MutableTreeNode parent = (MutableTreeNode)getParent();
            if (parent != null)
                parent.remove(this);
         * Sets this node's parent to <code>newParent</code> but does not
         * change the parent's child array.  This method is called from
         * <code>insert()</code> and <code>remove()</code> to
         * reassign a child's parent, it should not be messaged from anywhere
         * else.
         * @param     newParent     this node's new parent
        public void setParent(MutableTreeNode mutableTreeNode)
            this.parent = parent;
        public void setUserObject(Object obj)
            this.userObject = obj;
        public Element getXMLElement()
            return this.nodeElement;
        public String toString()
            return this.nodeElement.getTextTrim();
         * Returns true if <code>anotherNode</code> is an ancestor of this node
         * -- if it is this node, this node's parent, or an ancestor of this
         * node's parent.  (Note that a node is considered an ancestor of itself.)
         * If <code>anotherNode</code> is null, this method returns false.  This
         * operation is at worst O(h) where h is the distance from the root to
         * this node.
         * @see          #isNodeDescendant
         * @see          #getSharedAncestor
         * @param     anotherNode     node to test as an ancestor of this node
         * @return     true if this node is a descendant of <code>anotherNode</code>
        public boolean isNodeAncestor(TreeNode anotherNode)
            if (anotherNode == null)
                return false;
            TreeNode ancestor = this;
            do
                if (ancestor == anotherNode)
                    return true;
            } while((ancestor = ancestor.getParent()) != null);
            return false;
         * Returns true if <code>aNode</code> is a child of this node.  If
         * <code>aNode</code> is null, this method returns false.
         * @return     true if <code>aNode</code> is a child of this node; false if
         *            <code>aNode</code> is null
        public boolean isNodeChild(TreeNode aNode)
            boolean retval;
            if (aNode == null)
                retval = false;
            else
                if (getChildCount() == 0)
                    retval = false;
                else
                    retval = (aNode.getParent() == this);
            return retval;
         * Removes all of this node's children, setting their parents to null.
         * If this node has no children, this method does nothing.
        public void removeAllChildren()
            for (int i = getChildCount()-1; i >= 0; i--)
                remove(i);
         * Removes <code>newChild</code> from its parent and makes it a child of
         * this node by adding it to the end of this node's child array.
         * @see          #insert
         * @param     newChild     node to add as a child of this node
         * @exception     IllegalArgumentException    if <code>newChild</code>
         *                              is null
         * @exception     IllegalStateException     if this node does not allow
         *                              children
        public void add(MutableTreeNode newChild)
            if(newChild != null && newChild.getParent() == this)
                insert(newChild, getChildCount() - 1);
            else
                insert(newChild, getChildCount());
         * Indicates whether some other object is "equal to" this one.
         * @param   obj   the reference object with which to compare.
         * @return  <code>true</code> if this object is the same as the obj
         *          argument; <code>false</code> otherwise.
        public boolean equals(XMLNode node)
            boolean retValue;
            retValue = (this.getXMLElement().getTextTrim().equals(node.getXMLElement().getTextTrim())) &&
                    (this.getXMLElement().getParent().getTextTrim().equals(node.getXMLElement().getParent().getTextTrim()));
            return retValue;
    * XMLTreeModel.java
    * Created on December 20, 2004, 11:29 AM
    package debopam.utils.xml;
    import java.io.File;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    import java.util.EventListener;
    import java.util.List;
    import java.util.Vector;
    import javax.swing.event.EventListenerList;
    import javax.swing.event.TreeModelEvent;
    import javax.swing.event.TreeModelListener;
    import javax.swing.tree.TreeModel;
    import javax.swing.tree.TreePath;
    import org.jdom.Document;
    import org.jdom.Element;
    import org.jdom.input.SAXBuilder;
    * @author Debopam Ghoshal
    public class XMLTreeModel implements TreeModel
        private XMLNode rootNode;
        private String xmlFileName;
        private Document xmlDocument;
        /** Listeners. */
        protected EventListenerList listenerList = new EventListenerList();
         * Determines how the <code>isLeaf</code> method figures
         * out if a node is a leaf node. If true, a node is a leaf
         * node if it does not allow children. (If it allows
         * children, it is not a leaf node, even if no children
         * are present.) That lets you distinguish between <i>folder</i>
         * nodes and <i>file</i> nodes in a file system, for example.
         * <p>
         * If this value is false, then any node which has no
         * children is a leaf node, and any node may acquire
         * children.
         * @see TreeNode#getAllowsChildren
         * @see TreeModel#isLeaf
         * @see #setAsksAllowsChildren
        protected boolean asksAllowsChildren;
        /** Creates a new instance of XMLTreeModel */
        public XMLTreeModel(String xmlFileName, boolean asksAllowsChildren)
            this.xmlFileName = xmlFileName;
            this.asksAllowsChildren = asksAllowsChildren;
            loadXMLDocument();
            rootNode = makeRootNode();
        public XMLTreeModel(String xmlFileName)
            this(xmlFileName, false);
        private void loadXMLDocument()
            System.out.println("loading xml document...");
            try
                this.xmlDocument = null;
                this.xmlDocument = new SAXBuilder().build(new File(xmlFileName));
            catch(Exception x)
                System.out.println("Error while loading XML Document.");
                x.printStackTrace();
        private XMLNode makeRootNode()
            XMLNode root = new XMLNode(xmlDocument.getRootElement(), true);
            addChildren(root, xmlDocument.getRootElement());
            return root;
        private void addChildren(XMLNode parentXMLNode, Element element)
            List children = element.getChildren();
            for(int i = 0; i < children.size(); i++)
                Element childElement = (Element)children.get(i);
                XMLNode childNode = new XMLNode(childElement, true);
                parentXMLNode.add(childNode);
                addChildren(childNode, childElement);
         * 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.
        public void setAsksAllowsChildren(boolean newValue)
            asksAllowsChildren = newValue;
         * Tells how leaf nodes are determined.
         * @return true if only nodes which do not allow children are
         *         leaf nodes, false if nodes which have no children
         *         (even if allowed) are leaf nodes
         * @see #asksAllowsChildren
        public boolean asksAllowsChildren()
            return asksAllowsChildren;
         * Returns the child of <I>parent</I> at index <I>index</I> in the parent's
         * child array.  <I>parent</I> must be a node previously obtained from
         * this data source. This should not return null if <i>index</i>
         * is a valid index for <i>parent</i> (that is <i>index</i> >= 0 &&
         * <i>index</i> < getChildCount(<i>parent</i>)).
         * @param   parent  a node in the tree, obtained from this data source
         * @return  the child of <I>parent</I> at index <I>index</I>
        public Object getChild(Object parent, int index)
            return ((XMLNode)parent).getChildAt(index);
         * Returns the number of children of <I>parent</I>.  Returns 0 if the node
         * is a leaf or if it has no children.  <I>parent</I> must be a node
         * previously obtained from this data source.
         * @param   parent  a node in the tree, obtained from this data source
         * @return  the number of children of the node <I>parent</I>
        public int getChildCount(Object parent)
            return ((XMLNode)parent).getChildCount();
         * Returns the index of child in parent.
         * If either the parent or child is <code>null</code>, returns -1.
         * @param parent a note in the tree, obtained from this data source
         * @param child the node we are interested in
         * @return the index of the child in the parent, or -1
         *    if either the parent or the child is <code>null</code>
        public int getIndexOfChild(Object parent, Object child)
            if(parent == null || child == null)
                return -1;
            return ((XMLNode)parent).getIndex((XMLNode)child);
         * Sets the root to <code>root</code>. A null <code>root</code> implies
         * the tree is to display nothing, and is legal.
        public void setRoot(XMLNode rootNode)
            Object oldRoot = this.rootNode;
            this.rootNode = rootNode;
            if (rootNode == null && oldRoot != null)
                fireTreeStructureChanged(this, null);
            else
                nodeStructureChanged(rootNode);
         * Returns the root of the tree.  Returns null only if the tree has
         * no nodes.
         * @return  the root of the tree
        public Object getRoot()
            return rootNode;
         * 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
        public boolean isLeaf(Object node)
            if(asksAllowsChildren)
                return !((XMLNode)node).getAllowsChildren();
            return ((XMLNode)node).isLeaf();
         * This sets the user object of the TreeNode identified by path
         * and posts a node changed.  If you use custom user objects in
         * the TreeModel you're going to need to subclass this and
         * set the user object of the changed node to something meaningful.
        public void valueForPathChanged(TreePath path, Object newValue)
            XMLNode aNode = (XMLNode)path.getLastPathComponent();
            aNode.setUserObject(newValue);
            nodeChanged(aNode);
         * Invoked this to insert newChild at location index in parents children.
         * This will then message nodesWereInserted to create the appropriate
         * event. This is the preferred way to add children as it will create
         * the appropriate event.
        public void insertNodeInto(XMLNode newChild, XMLNode parent, int index)
            parent.insert(newChild, index);
            int[] newIndexs = new int[1];
            newIndexs[0] = index;
            nodesWereInserted(parent, newIndexs);
         * Message this to remove node from its parent. This will message
         * nodesWereRemoved to create the appropriate event. This is the
         * preferred way to remove a node as it handles the event creation
         * for you.
        public void removeNodeFromParent(XMLNode node)
            XMLNode parent = (XMLNode)node.getParent();
            if(parent == null)
                throw new IllegalArgumentException("node does not have a parent.");
            int[] childIndex = new int[1];
            Object[] removedArray = new Object[1];
            childIndex[0] = parent.getIndex(node);
            parent.remove(childIndex[0]);
            removedArray[0] = node;
            nodesWereRemoved(parent, childIndex, removedArray);
         * Invoke this method after you've changed how node is to be
         * represented in the tree.
        public void nodeChanged(XMLNode node)
            if(listenerList != null && node != null)
                XMLNode parent = (XMLNode)node.getParent();
                if(parent != null)
                    int        anIndex = parent.getIndex(node);
                    if(anIndex != -1)
                        int[] cIndexs = new int[1];
                        cIndexs[0] = anIndex;
                        nodesChanged(parent, cIndexs);
                else if (node == getRoot())
                    nodesChanged(node, null);
         * Invoke this method if you've modified the TreeNodes upon which this
         * model depends.  The model will notify all of its listeners that the
         * model has changed.
        public void reload()
            loadXMLDocument();
            XMLNode tempRootNode = makeRootNode();
            if(!tempRootNode.equals(rootNode))
                // Means that the root node itself has changed.
                System.out.println("Root node changed");
                reload(rootNode);
            //else
                checkForNodesChanged(tempRootNode, rootNode);
         * Invoke this method if you've modified the TreeNodes upon which this
         * model depends.  The model will notify all of its listeners that the
         * model has changed below the node <code>node</code> (PENDING).
        public void reload(XMLNode node)
            if(node != null)
                fireTreeStructureChanged(this, getPathToRoot(node), null, null);
         * Invoke this method after you've inserted some TreeNodes into
         * node.  childIndices should be the index of the new elements and
         * must be sorted in ascending order.
        public void nodesWereInserted(XMLNode node, int[] childIndices)
            if(listenerList != null && node != null && childIndices != null
                    && childIndices.length > 0)
                int               cCount = childIndices.length;
                Object[]          newChildren = new Object[cCount];
                for(int counter = 0; counter < cCount; counter++)
                    newChildren[counter] = node.getChildAt(childIndices[counter]);
                fireTreeNodesInserted(this, getPathToRoot(node), childIndices,
                        newChildren);
         * Invoke this method after you've removed some TreeNodes from
         * node.  childIndices should be the index of the removed elements and
         * must be sorted in ascending order. And removedChildren should be
         * the array of the children objects that were removed.
        public void nodesWereRemoved(XMLNode node, int[] childIndices,
                Object[] removedChildren)
            if(node != null && childIndices != null)
                fireTreeNodesRemoved(this, getPathToRoot(node), childIndices,
                        removedChildren);
         * Invoke this method after you've changed how the children identified by
         * childIndicies are to be represented in the tree.
        public void nodesChanged(XMLNode node, int[] childIndices)
            if(node != null)
                if (childIndices != null)
                    int cCount = childIndices.length;
                    if(cCount > 0)
                        Object[] cChildren = new Object[cCount];
                        for(int counter = 0; counter < cCount; counter++)
                            cChildren[counter] = node.getChildAt
                                    (childIndices[counter]);
                        fireTreeNodesChanged(this, getPathToRoot(node),
                                childIndices, cChildren);
                else if (node == getRoot())
                    fireTreeNodesChanged(this, getPathToRoot(node), null, null);
         * Invoke this method if you've totally changed the children of
         * node and its childrens children...  This will post a
         * treeStructureChanged event.
        public void nodeStructureChanged(XMLNode node)
            if(node != null)
                fireTreeStructureChanged(this, getPathToRoot(node), null, null);
         * Builds the parents of node up to and including the root node,
         * where the original node is the last element in the returned array.
         * The length of the returned array gives the node's depth in the
         * tree.
         * @param aNode the TreeNode to get the path for
        public XMLNode[] getPathToRoot(XMLNode aNode)
            return getPathToRoot(aNode, 0);
         * Builds the parents of node up to and including the root node,
         * where the original node is the last element in the returned array.
         * The length of the returned array gives the node's depth in the
         * tree.
         * @param aNode  the TreeNode to get the path for
         * @param depth  an int giving the number of steps already taken towards
         *        the root (on recursive calls), used to size the returned array
         * @return an array of TreeNodes giving the path from the root to the
         *         specified node
        protected XMLNode[] getPathToRoot(XMLNode aNode, int depth)
            XMLNode[] retNodes;
            // This method recurses, traversing towards the root in order
            // size the array. On the way back, it fills in the nodes,
            // starting from the root and working back to the original node.
            /* Check for null, in case someone passed in a null node, or
               they passed in an element that isn't rooted at root. */
            if(aNode == null)
                if(depth == 0)
                    return null;
                else
                    retNodes = new XMLNode[depth];
            else
                depth++;
                if(aNode == rootNode)
                    retNodes = new XMLNode[depth];
                else
                    retNodes = getPathToRoot((XMLNode)aNode.getParent(), depth);
                retNodes[retNodes.length - depth] = aNode;
            return retNodes;
        //  Events
         * Adds a listener for the TreeModelEvent posted after the tree changes.
         * @see     #removeTreeModelListener
         * @param   l       the listener to add
        public void addTreeModelListener(TreeModelListener l)
            listenerList.add(TreeModelListener.class, l);
         * Removes a listener previously added with <B>addTreeModelListener()</B>.
         * @see     #addTreeModelListener
         * @param   l       the listener to remove
        public void removeTreeModelListener(TreeModelListener l)
            listenerList.remove(TreeModelListener.class, l);
         * Returns an array of all the tree model listeners
         * registered on this model.
         * @return all of this model's <code>TreeModelListener</code>s
         *         or an empty
         *         array if no tree model listeners are currently registered
         * @see #addTreeModelListener
         * @see #removeTreeModelListener
         * @since 1.4
        public TreeModelListener[] getTreeModelListeners()
            return (TreeModelListener[])listenerList.getListeners(
                    TreeModelListener.class);
         * Notifies all listeners that have registered interest for
         * notification on this event type.  The event instance
         * is lazily created using the parameters passed into
         * the fire method.
         * @param source the node being changed
         * @param path the path to the root node
         * @param childIndices the indices of the changed elements
         * @param children the changed elements
         * @see EventListenerList
        protected void fireTreeNodesChanged(Object source, Object[] path,
                int[] childIndices,
                Object[] children)
            // Guaranteed to return a non-null array
            Object[] listeners = listenerList.getListenerList();
            TreeModelEvent e = null;
            // Process the listeners last to first, notifying
            // those that are interested in this event
            for (int i = listeners.length-2; i>=0; i-=2)
                if (listeners==TreeModelListener.class)
    // Lazily create the event:
    if (e == null)
    e = new TreeModelEvent(source, path,
    childIndices, children);
    ((TreeModelListener)listeners[i+1]).treeNodesChanged(e);
    * Notifies all listeners that have registered interest for
    * notification on this event type. The event instance

  • How to Create XML Schema From JTree ?

    Please help me... Thank you.
    This is Code
    Tree.java ----- Run This File
    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.tree.DefaultMutableTreeNode;
    public class Tree extends JPanel implements ActionListener {
        private int newNodeSuffix = 1;
        private static String ADD_COMMAND = "add";
        private static String REMOVE_COMMAND = "remove";
        private static String CLEAR_COMMAND = "clear";
        private static String OK_COMMAND = "ok";
        private DynamicTree treePanel;
        public Tree() {
            super(new BorderLayout());
            //Create the components.
            treePanel = new DynamicTree();
            //populateTree(treePanel);
            JButton addButton = new JButton("Add");
            addButton.setActionCommand(ADD_COMMAND);
            addButton.addActionListener(this);
            JButton removeButton = new JButton("Remove");
            removeButton.setActionCommand(REMOVE_COMMAND);
            removeButton.addActionListener(this);
            JButton clearButton = new JButton("Clear");
            clearButton.setActionCommand(CLEAR_COMMAND);
            clearButton.addActionListener(this);
            JButton okButton = new JButton("OK");
            okButton.setActionCommand(OK_COMMAND);
            okButton.addActionListener(this);
            //Lay everything out.
            treePanel.setPreferredSize(new Dimension(300, 150));
            add(treePanel, BorderLayout.CENTER);
            JPanel panel = new JPanel(new GridLayout(0,1));
            panel.add(addButton);
            panel.add(removeButton);
            panel.add(clearButton);
            panel.add(okButton);
            add(panel, BorderLayout.LINE_END);
        /*public void populateTree(DynamicTree treePanel) {
            String p1Name = new String("Parent 1");
            //String p2Name = new String("Parent 2");
            String c1Name = new String("Child 1");
            //String c2Name = new String("Child 2");
            DefaultMutableTreeNode p1;
            p1 = treePanel.addObject(null, p1Name);
            //p2 = treePanel.addObject(null, p2Name);
            treePanel.addObject(p1, c1Name);
            //treePanel.addObject(p1, c2Name);
            //treePanel.addObject(p2, c1Name);
            //treePanel.addObject(p2, c2Name);
        public void actionPerformed(ActionEvent e) {
            String command = e.getActionCommand();
            if (ADD_COMMAND.equals(command)) {
                //Add button clicked.
                treePanel.addObject("New Node " + newNodeSuffix++);
            } else if (REMOVE_COMMAND.equals(command)) {
                //Remove button clicked.
                treePanel.removeCurrentNode();
            } else if (CLEAR_COMMAND.equals(command)) {
                //Clear button clicked.
                treePanel.clear();
            } else if (OK_COMMAND.equals(command)) {
                 //Ok button clicked.
                 treePanel.ok();
         * Create the GUI and show it.  For thread safety,
         * this method should be invoked from the
         * event-dispatching thread.
        private static void createAndShowGUI() {
            //Create and set up the window.
            JFrame frame = new JFrame("Craete XML Tree");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            //Create and set up the content pane.
            Tree newContentPane = new Tree();
            newContentPane.setOpaque(true); //content panes must be opaque
            frame.setContentPane(newContentPane);
            //Display the window.
            frame.pack();
            frame.setVisible(true);
        public static void main(String[] args) {
            //Schedule a job for the event-dispatching thread:
            //creating and showing this application's GUI.
            javax.swing.SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    createAndShowGUI();
    }DynamicTree.java
    import javax.swing.JOptionPane;
    import java.awt.GridLayout;
    import java.awt.Toolkit;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTree;
    import javax.swing.tree.DefaultMutableTreeNode;
    import javax.swing.tree.DefaultTreeModel;
    import javax.swing.tree.MutableTreeNode;
    import javax.swing.tree.TreePath;
    import javax.swing.tree.TreeSelectionModel;
    import javax.swing.event.TreeModelEvent;
    import javax.swing.event.TreeModelListener;
    public class DynamicTree extends JPanel {
        protected DefaultMutableTreeNode rootNode;
        protected DefaultTreeModel treeModel;
        protected JTree tree;
        private Toolkit toolkit = Toolkit.getDefaultToolkit();
        public DynamicTree() {
            super(new GridLayout(1,0));
            rootNode = new DefaultMutableTreeNode("Root Node");
            treeModel = new DefaultTreeModel(rootNode);
            treeModel.addTreeModelListener(new MyTreeModelListener());
            tree = new JTree(treeModel);
            tree.setEditable(true);
            tree.getSelectionModel().setSelectionMode
                    (TreeSelectionModel.SINGLE_TREE_SELECTION);
            tree.setShowsRootHandles(true);
            JScrollPane scrollPane = new JScrollPane(tree);
            add(scrollPane);
        /** Remove all nodes except the root node. */
        public void clear() {
            rootNode.removeAllChildren();
            treeModel.reload();
        public void ok() {
             int n = JOptionPane.showConfirmDialog(null, "Do you want to create XML Schema?", "", JOptionPane.YES_NO_OPTION);
        /** Remove the currently selected node. */
        public void removeCurrentNode() {
            TreePath currentSelection = tree.getSelectionPath();
            if (currentSelection != null) {
                DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode)
                             (currentSelection.getLastPathComponent());
                MutableTreeNode parent = (MutableTreeNode)(currentNode.getParent());
                if (parent != null) {
                    treeModel.removeNodeFromParent(currentNode);
                    return;
            // Either there was no selection, or the root was selected.
            toolkit.beep();
        /** Add child to the currently selected node. */
        public DefaultMutableTreeNode addObject(Object child) {
            DefaultMutableTreeNode parentNode = null;
            TreePath parentPath = tree.getSelectionPath();
            if (parentPath == null) {
                parentNode = rootNode;
            } else {
                parentNode = (DefaultMutableTreeNode)
                             (parentPath.getLastPathComponent());
            return addObject(parentNode, child, true);
        public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent,
                                                Object child) {
            return addObject(parent, child, false);
        public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent,
                                                Object child,
                                                boolean shouldBeVisible) {
            DefaultMutableTreeNode childNode =
                    new DefaultMutableTreeNode(child);
            if (parent == null) {
                parent = rootNode;
            treeModel.insertNodeInto(childNode, parent,
                                     parent.getChildCount());
            //Make sure the user can see the lovely new node.
            if (shouldBeVisible) {
                tree.scrollPathToVisible(new TreePath(childNode.getPath()));
            return childNode;
        class MyTreeModelListener implements TreeModelListener {
            public void treeNodesChanged(TreeModelEvent e) {
                DefaultMutableTreeNode node;
                node = (DefaultMutableTreeNode)
                         (e.getTreePath().getLastPathComponent());
                 * If the event lists children, then the changed
                 * node is the child of the node we've already
                 * gotten.  Otherwise, the changed node and the
                 * specified node are the same.
                try {
                    int index = e.getChildIndices()[0];
                    node = (DefaultMutableTreeNode)
                           (node.getChildAt(index));
                } catch (NullPointerException exc) {}
                System.out.println("The user has finished editing the node.");
                System.out.println("New value: " + node.getUserObject());
            public void treeNodesInserted(TreeModelEvent e) {
            public void treeNodesRemoved(TreeModelEvent e) {
            public void treeStructureChanged(TreeModelEvent e) {
    }

    XML shema is basically an XML file. So u need to know how to create an XML,
    provided u know how the shema file should be.
    Creating an XML :
    http://forum.java.sun.com/thread.jspa?threadID=5181031&messageID=9705786#9705786

  • Compiler bug in 10.1.3 EA1?  get "Internal compilation error" with EnumSet

    The code sample below generates "Error: Internal compilation error, terminated with a fatal exception" when doing make. It's a very simple example, it creates an EnumSet with one element and dumps it via the "toString()" method.
    If I change the line:
    "EnumSet set = EnumSet.of(Buttons.ONE);"
    To:
    "EnumSet set = EnumSet.allOf(c);"
    It works fine. For some reason the "of" method of "EnumSet" crashes the compiler.
    Any ideas?
    ========================================
    package mypackage;
    import java.util.EnumSet;
    public class EnumDemo
    enum Buttons { ONE, TWO, THREE }
    public EnumDemo()
    public void dump()
              Class c = Buttons.class;
              EnumSet set = EnumSet.of(Buttons.ONE);
              System.out.println(set.toString());
    public static void main(String[] args)
    EnumDemo cls = new EnumDemo();
    cls.dump();
    ==============================

    package com.esp.main;
    import java.awt.Dimension;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import javax.swing.JTree;
    import javax.swing.event.TreeModelEvent;
    import javax.swing.event.TreeModelListener;
    import javax.swing.event.TreeSelectionEvent;
    import javax.swing.event.TreeSelectionListener;
    import javax.swing.tree.DefaultTreeModel;
    import javax.swing.tree.TreePath;
    public class TreeNavigator extends JTree {
    private FormMain fm;
    public TreeNavigatorNode selectedTreeNode;
    public TreePath selectedTreePath;
    public JTree thisTree;
    public TreeNavigator(FormMain pFM) {
    fm = pFM;
    thisTree = this;
    addTreeSelectionListener(new TreeSelectionListener() {
    public void valueChanged(TreeSelectionEvent e) {
    selectedTreeNode = (TreeNavigatorNode)thisTree.getLastSelectedPathComponent();
    if (selectedTreeNode == null) {
    return;
    selectedTreePath = e.getPath();
    addMouseListener(new MouseAdapter() {
    public void mouseReleased(MouseEvent e) {
    if (e.getClickCount() == 1) {
    doPopup(e.getX(), e.getY());
    String nodeInternalFrameClassName = selectedTreeNode.getInternalFrameClassName();
    String nodeNodeTypeDesc = selectedTreeNode.getNodeTypeDesc();
    if ((selectedTreeNode != null) && (nodeNodeTypeDesc.equals("FORM") || nodeNodeTypeDesc.equals("GRAPH"))) {
    fm.showInternalFrame(nodeInternalFrameClassName, fm, null);
    } else if (e.getClickCount() == 1) {
    TreePath path = thisTree.getClosestPathForLocation(e.getX(), e.getY());
    thisTree.setSelectionPath(path);
    public void doPopup(int x, int y) {
    if ((selectedTreeNode != null) && selectedTreeNode.nodeTypeDesc.equals("MODULE")) {
    fm.cm.sendString("Do Nothing");
    } else {
    fm.cm.sendString("Launch form");
    setEditable(false);
    setMaximumSize(new java.awt.Dimension(3200, 3200));
    setPreferredSize(new java.awt.Dimension(800, 100));
    setShowsRootHandles(false);
    setLargeModel(false);
    setRootVisible(false);
    setDragEnabled(false);
    DefaultTreeModel treeNavigatorModel = new DefaultTreeModel(fm.treeNavigatorNodeArray[fm.rootNode], true);
    treeModel.addTreeModelListener(new NavigatorTreeModelListener());
    setModel(treeNavigatorModel);
    expandAll(this);
    try {
    jbInit();
    } catch (Exception e) {
    e.printStackTrace();
    public void expandAll(JTree tree) {
    int row = 0;
    while (row < tree.getRowCount()) {
    tree.expandRow(row);
    row++;
    private void jbInit() throws Exception {
    this.setSize(new Dimension(286, 383));
    TreeNavigatorCellRenderer renderer = new TreeNavigatorCellRenderer(fm);
    this.setCellRenderer(renderer);
    class NavigatorTreeModelListener implements TreeModelListener {
    public void treeNodesChanged(TreeModelEvent e) {
    TreeNavigatorNode node;
    node = (TreeNavigatorNode)(e.getTreePath().getLastPathComponent());
    * If the event lists children, then the changed
    * node is the child of the node we've already
    * gotten. Otherwise, the changed node and the
    * specified node are the same.
    try {
    int index = e.getChildIndices()[0];
    node = (TreeNavigatorNode)(node.getChildAt(index));
    } catch (NullPointerException exc) {
    public void treeNodesInserted(TreeModelEvent e) {
    public void treeNodesRemoved(TreeModelEvent e) {
    public void treeStructureChanged(TreeModelEvent e) {
    }

Maybe you are looking for

  • How can I delete all of my calendars and start over from scratch?

    I am sure this is an easy question because it seems that others before me have probably been in this situation. I wish to delete my calendars (and todo lists, etc) in iCal. In essence I want to start over from scratch as if I had not yet used iCal. D

  • Locating Photoshop CS5 EE Download File

    Hi - I have a licence for Photoshop CS5 originally supplied on disk. Now want to find a download so I can re-install on my new laptop. Where can I locate a download please. Thanks, Mike

  • Info record multiple BOM version - problem

    Dear Experts, We are facing one issue with info record. In our business scenario, we have two sub-contractor BOM with same FG Component , But while create purchase order system pickup 1st BOM , We have facility to update version in info record i.e. o

  • Photo's won't transfer to my 5th gen. video ipod in itunes 7.0.1.8

    I plug in my ipod and it does it's bussiness but part way through I get this error message: the ipod "my ipod" cannot be updated. the required file cannot be found. I found that everything else is transfered correctly ie music, music videos, movies,

  • Creating a CSR for MARS

    Is there anyway to create a CSR request to use a real SSL cert for the MARS instead of using the self signed cert?