• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 419
  • Last Modified:

Removing all selected nodes within a JTree

A "delete selected nodes" button invokes the following code when pressed:


DefaultTreeModel model = (DefaultTreeModel ) my_tree.getModel() ;
TreePath [] tps = my_tree.getSelectionPaths() ;

for ( int i=0; i<tps.length; i++ )
{
    MutableTreeNode node = (MutableTreeNode ) tps[i].getLastPathComponent() ;
    model.removeNodeFromParent( node ) ;
}


However, I get a ClassCastException on this line:

    DefaultTreeModel model = (DefaultTreeModel ) getModel() ;


Why is this?

Could it be anything to do with the fact that I'm assigning a custom TreeModel when I instantiate my JTree ?


Thanks.
0
InteractiveMind
Asked:
InteractiveMind
  • 8
  • 7
1 Solution
 
CEHJCommented:
>>Could it be anything to do with the fact that I'm assigning a custom TreeModel when I instantiate my JTree ?

Yes. See what type it is:

System.out.println(my_tree.getModel().getClass());
0
 
InteractiveMindAuthor Commented:
public class FileTreeModel implements TreeModel, Serializable, Cloneable
{ .. }
0
 
CEHJCommented:
Ah *that* one ;-) That won't support removal of nodes as is. That would need adaptation to something like a subclass of DefaultTreeModel
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
InteractiveMindAuthor Commented:
Ah right;

so, I've extended DefaultTreeModel... but I need to pass a TreeNode to the super's constructor... what would that need to be?
0
 
CEHJCommented:
That'd need to be a TreeNode based on the directory tree root
0
 
InteractiveMindAuthor Commented:
Okay, here's what I've tried:

    super( new DefaultMutableTreeNode( new File( "C:\\" ) ) ) ;

It's no longer giving me any errors when I cast getModel() to DefaultTreeModel.


However, I get the following exception:

    java.lang.ClassCastException: java.io.File

on this line:

    MutableTreeNode node = (MutableTreeNode ) tps[i].getLastPathComponent() ;


I'm guessing that due to my node's being File's, that getLastPathComponent() is returning a File object ?

But a File object doesn't seem to be highly useful for me here... how can I fix this ??
0
 
CEHJCommented:
You need to arrange it so that every node of the tree has a userObject of type File. It's not sufficient just to fix the root node
0
 
InteractiveMindAuthor Commented:
All nodes within the tree are File objects.
0
 
CEHJCommented:
You need to make them of the same type as the root node you just created
0
 
InteractiveMindAuthor Commented:
Hm, how would I do that?

Here's my tree model as things stand:


import javax.swing.* ;
import javax.swing.tree.* ;
import javax.swing.event.* ;
import java.awt.Component ;
import java.awt.event.* ;
import java.util.* ;
import java.io.* ;

public class FileTreeModel extends DefaultTreeModel implements Serializable, Cloneable
{
      
      // V A R I A B L E S
      
      protected EventListenerList listeners ;
      private static final Object LEAF = new Serializable() {} ;
      private Map map ;
      private File root ;
      
      
      // C O N S T R U C T O R
      
      public FileTreeModel( File root )
      {
            super( new DefaultMutableTreeNode( new File( "C:\\" ) ) ) ;
            
            this.root = root ;

            if ( !root.isDirectory() )
                  map.put( root, LEAF ) ;

            this.listeners = new EventListenerList() ;

            this.map = new HashMap() ;
      }
      
      
      // P U B L I C   M E T H O D S
      
      public Object getRoot()
      {
            return root ;
      }

      public boolean isLeaf( Object node )
      {
            return map.get( node ) == LEAF ;
      }

      public int getChildCount( Object node )
      {
            List children = children( node ) ;

            if ( children == null )
                  return 0 ;

            return children.size() ;
      }

      public Object getChild( Object parent, int index )
      {
            return children( parent ).get( index ) ;
      }

      public int getIndexOfChild( Object parent, Object child )
      {
            return children( parent ).indexOf( child ) ;
      }
      
      protected List children( Object node )
      {
            File f = (File ) node ;

            Object value = map.get( f ) ;

            if ( value == LEAF )
                  return null ;

            List children = (List ) value ;

            if ( children == null )
            {
                  File [] c = f.listFiles() ;

                  if ( c != null )
                  {
                        children = new ArrayList( c.length ) ;

                        for ( int len = c.length, i = 0 ; i < len ; i++ )
                        {
                              children.add( c [i] ) ;
                              if ( !c [i].isDirectory() )
                                    map.put( c [i], LEAF ) ;
                        }
                  } else
                        children = new ArrayList( 0 ) ;
                  
                  
                  map.put( f, children ) ;
            }

            return children ;
      }

      public void valueForPathChanged( TreePath path, Object value )
      {}

      public void addTreeModelListener( TreeModelListener l )
      {
            listeners.add( TreeModelListener.class, l ) ;
      }

      public void removeTreeModelListener( TreeModelListener l )
      {
            listeners.remove( TreeModelListener.class, l ) ;
      }
      
      
      public Object clone()
      {
            try
            {
                  FileTreeModel clone = (FileTreeModel ) super.clone() ;

                  clone.listeners = new EventListenerList() ;

                  clone.map = new HashMap( map ) ;

                  return clone ;
            } catch ( CloneNotSupportedException e )
            {
                  throw new InternalError() ;
            }
      }
      
}

0
 
CEHJCommented:
Looks like in the children method, you need to get that Map arranged to have DefaultMutableTreeNode as its keys and List of the same as its values. The nodes, of course, will be initialized with File
0
 
InteractiveMindAuthor Commented:
Hm.

Here's what I'm trying to achieve (as you've probably guessed):

The user can delete a node within the file tree - which deletes the corresponding file on the hard drive, and also removes the selected node (of course).

I was just thinking.... would it be easier to just delete the selected file (I can do this bit), and then refresh the tree model?

I know how to refresh the tree model, as to update it (so, in effect, the deleted file's node also dissappears)... However, when I refresh the tree model, all of the expanded nodes collapse.. Is there a way of recording which nodes have been expanded, and then just re-expanding them after the tree model has been refreshed?
0
 
CEHJCommented:
The simplification is possible and probably desirable, but there's a possibilty you may run into problems by not having 'real nodes' further down the line.

You could record the expansions and restore them later:

http://java.sun.com/docs/books/tutorial/uiswing/events/treeexpansionlistener.html
0
 
InteractiveMindAuthor Commented:
Yer, I'll do that. :)

Cheers CEHJ.
0
 
CEHJCommented:
:-)
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 8
  • 7
Tackle projects and never again get stuck behind a technical roadblock.
Join Now