How would you insert one node into another at the treepath?

20
January 11, 2019, at 10:20 AM

I have two nodes and one TreePath in Java Swing. One node contains the 'root' node (let's call this nodeA), it contains everything under it . The second node is the 'new' Node (let's call this nodeB), it contains a new node. I have a TreePath that shows where I want to insert nodeB in nodeA. I am trying to develop a function to do this. Any help? Thanks in advance!

Node A   
 ~
      Documents
         -- text1.txt
         -- text2.txt
      Pictures
         - text1.txt

I want to insert the below node into the Pictures folder

folder1
   -- newtext1.txt

My insertNodes function:

private static void insertNodes
        (DefaultMutableTreeNode root
            ,DefaultMutableTreeNode newNode
                ,String tp)
{
    String[] elements = tp.split("/");
    String treePath = "";
    for (int i=0; i<elements.length-1; i++)
    {
        if (i == elements.length-2)
        {
            treePath += elements[i];
        } else {
        treePath += elements[i] + "/" ;
        }
    }
    System.out.println("TreePath : " + treePath);
    DefaultMutableTreeNode node = buildNodeFromString(treePath);
    DefaultMutableTreeNode lastLeaf = node.getLastLeaf();
    TreePath path = new TreePath(lastLeaf.getPath());
    System.out.println("insertNodes-Path =" + path);
    DefaultTreeModel model = new DefaultTreeModel(root);

    DefaultMutableTreeNode pictureNode = (DefaultMutableTreeNode) path.getLastPathComponent();
    pictureNode.add(newNode);


    // Notify the model of the changes
    model.nodesWereInserted(pictureNode, new int[]{pictureNode.getChildCount() - 1});
    // The above way (you suggested) wipes out everything and just puts one "~" in the JTree

    // The below line adds them all to the "~" direcotry
    //root.add(newNode); 

}

My getFileStructure (where I call insertNodes)

    public static DefaultMutableTreeNode getFileStructure(FTPClient client,String workingPath,DefaultMutableTreeNode style )
{
try {
    System.out.println("\n");
    System.out.println("Working Path: " + workingPath);
    FTPFile[] files = client.listFiles(workingPath);
    DefaultMutableTreeNode node = buildNodeFromString(workingPath);
    DefaultMutableTreeNode lastLeaf = node.getLastLeaf();
    TreePath path = new TreePath(lastLeaf.getPath());
    System.out.println("Path =" + path);
    DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode)(path.getLastPathComponent());       
    System.out.println("Add to Node:" + selectedNode.toString());
    for (FTPFile file : files) {
        if (file.isDirectory())
        {
            // DefaultMutableTreeNode fileDirectory =new DefaultMutableTreeNode(file.getName());
            // selectedNode.add(fileDirectory);
            System.out.println("\t Folder Name: " + file.getName());
            getFileStructure(client, workingPath + "/" + file.getName(),style);
        } else {
        DefaultMutableTreeNode root =new DefaultMutableTreeNode();  
        System.out.println("Filename: " + file.getName());
        DefaultMutableTreeNode fileDirectory =new DefaultMutableTreeNode(file.getName());

        selectedNode.add(fileDirectory);
        System.out.println("Added to node = " + selectedNode.toString());
        System.out.println("First Node = " + selectedNode.getFirstChild().toString());
        System.out.println("Last Node = " + selectedNode.getLastChild().toString());
        System.out.println("Num of Children = " + selectedNode.getLeafCount());
        System.out.println("Depth Count= " + selectedNode.getDepth());
        }
    }
    insertNodes(style,selectedNode,workingPath);        
} catch (IOException ex) {
    System.out.println("IOException:" + ex);
 } 

 return style;
}
Answer 1

Okay, some assumptions, lets assume you have a TreeModel which looks something like this...

DefaultMutableTreeNode root = new DefaultMutableTreeNode("~");
DefaultTreeModel model = new DefaultTreeModel(root);
DefaultMutableTreeNode docs = new DefaultMutableTreeNode("Documents");
docs.add(new DefaultMutableTreeNode("text1.txt"));
docs.add(new DefaultMutableTreeNode("text2.txt"));
root.add(docs);
DefaultMutableTreeNode pics = new DefaultMutableTreeNode("Pictures");
pics.add(new DefaultMutableTreeNode("text1.txt"));
root.add(pics);

This will generate a tree which looks something like...

+ ~
  + Documents
    - text1.txt
    - text2.txt
  + Pictures
    - text1.txt

Then, lets assume you know want to add...

DefaultMutableTreeNode newFolder = new DefaultMutableTreeNode("folder1");
newFolder.add(new DefaultMutableTreeNode("text1.txt"));

to ~/Pictures.

Assuming you have a valid TreePath off [~, Pictures], you can simply get the lastComponent from the path, which will be a reference to the Pictures TreeNode, then you can simply do something like...

DefaultMutableTreeNode pictureNode = (DefaultMutableTreeNode) treePathFromPicturesToRoot.getLastPathComponent();
pictureNode.add(newFolder);
// Notify the model of the changes
model.nodesWereInserted(pictureNode, new int[]{pictureNode.getChildCount() - 1});

which will generate a tree like...

+ ~
  + Documents
    - text1.txt
    - text2.txt
  + Pictures
    - text1.txt
    + folder1
      - text1.txt

Now, I don't know where you TreePath is coming from, but I assume it's a valid path made up of the nodes which are actually in the TreeModel, otherwise this won't work very well

Now, this based on a number of examples, if this doesn't meet your needs, then you will need to provide a Minimal, Complete, and Verifiable example from which we can better understand you issue

Sample code...

I built the basic concept from using the following code

import java.util.Enumeration;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
public class Test {
    public static void main(String[] args) {
        DefaultMutableTreeNode root = new DefaultMutableTreeNode("~");
        DefaultTreeModel model = new DefaultTreeModel(root);
        DefaultMutableTreeNode docs = new DefaultMutableTreeNode("Documents");
        docs.add(new DefaultMutableTreeNode("text1.txt"));
        docs.add(new DefaultMutableTreeNode("text2.txt"));
        root.add(docs);
        DefaultMutableTreeNode pics = new DefaultMutableTreeNode("Pictures");
        pics.add(new DefaultMutableTreeNode("text1.txt"));
        root.add(pics);
        describe(model);
        DefaultMutableTreeNode newFolder = new DefaultMutableTreeNode("folder1");
        newFolder.add(new DefaultMutableTreeNode("text1.txt"));
        TreeNode[] pathToRoot = pics.getPath();
        TreePath treePathFromPicturesToRoot = new TreePath(pathToRoot);
        System.out.println(treePathFromPicturesToRoot);
        DefaultMutableTreeNode pictureNode = (DefaultMutableTreeNode) treePathFromPicturesToRoot.getLastPathComponent();
        pictureNode.add(newFolder);
        model.nodesWereInserted(pictureNode, new int[]{pictureNode.getChildCount() - 1});
        describe(model);
    }
    protected static void describe(DefaultTreeModel model) {
        describe((DefaultMutableTreeNode) model.getRoot(), 0);
    }
    protected static void describe(DefaultMutableTreeNode node, int level) {
        StringBuilder padding = new StringBuilder();
        for (int index = 0; index < level; index++) {
            padding.append("  ");
        }
        System.out.println(padding + "+ " + node);
        padding.append("  ");
        Enumeration<TreeNode> children = node.children();
        while (children.hasMoreElements()) {
            DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) children.nextElement();
            if (childNode.isLeaf()) {
                System.out.println(padding + "- " + childNode);
            } else {
                describe(childNode, level + 1);
            }
        }
    }
}
Updated based on additional code...

Your insert method should be just about as simple as...

private static void insertNodes(
        DefaultTreeModel model,
        DefaultMutableTreeNode parent,
        DefaultMutableTreeNode newNode) {
    parent.add(newNode);
    model.nodesWereInserted(parent, new int[]{parent.getChildCount() - 1});
}

To find a node based on a String path, you "might" be able to do something like...

protected static DefaultMutableTreeNode findNode(DefaultTreeModel model, String path) {
    DefaultMutableTreeNode node = (DefaultMutableTreeNode) model.getRoot();
    String[] parts = path.split("/");
    if (node.getUserObject().toString().equals(parts[0])) {
         return findNode(node, Arrays.copyOfRange(parts, 1, parts.length));
    }
    return null;
}
protected static DefaultMutableTreeNode findNode(DefaultMutableTreeNode node, String[] path) {
    if (path.length == 0) {
        return node;
    }
    Enumeration<TreeNode> children = node.children();
    while (children.hasMoreElements()) {
        DefaultMutableTreeNode child = (DefaultMutableTreeNode)children.nextElement();
        if (child.getUserObject().toString().equals(path[0])) {
            return findNode(node, Arrays.copyOfRange(path, 1, path.length));
        }
    }
    return null;
}

Which means that, based on my previous example, you could do something like...

DefaultMutableTreeNode newFolder = new DefaultMutableTreeNode("folder1");
newFolder.add(new DefaultMutableTreeNode("text1.txt"));
insertNodes(model, findNode(model, "~/Pictures"), newFolder);
Sample #2
import java.util.Arrays;
import java.util.Enumeration;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
public class Test {
    public static void main(String[] args) {
        DefaultMutableTreeNode root = new DefaultMutableTreeNode("~");
        DefaultTreeModel model = new DefaultTreeModel(root);
        DefaultMutableTreeNode docs = new DefaultMutableTreeNode("Documents");
        docs.add(new DefaultMutableTreeNode("text1.txt"));
        docs.add(new DefaultMutableTreeNode("text2.txt"));
        root.add(docs);
        DefaultMutableTreeNode pics = new DefaultMutableTreeNode("Pictures");
        pics.add(new DefaultMutableTreeNode("text1.txt"));
        root.add(pics);
        describe(model);
        DefaultMutableTreeNode newFolder = new DefaultMutableTreeNode("folder1");
        newFolder.add(new DefaultMutableTreeNode("text1.txt"));
        insertNodes(model, findNode(model, "~/Pictures"), newFolder);
        describe(model);
    }
    protected static DefaultMutableTreeNode findNode(DefaultTreeModel model, String path) {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode) model.getRoot();
        String[] parts = path.split("/");
        if (node.getUserObject().toString().equals(parts[0])) {
            return findNode(node, Arrays.copyOfRange(parts, 1, parts.length));
        }
        return null;
    }
    protected static DefaultMutableTreeNode findNode(DefaultMutableTreeNode node, String[] path) {
        if (path.length == 0) {
            return node;
        }
        Enumeration<TreeNode> children = node.children();
        while (children.hasMoreElements()) {
            DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement();
            if (child.getUserObject().toString().equals(path[0])) {
                return findNode(child, Arrays.copyOfRange(path, 1, path.length));
            }
        }
        return null;
    }
    private static void insertNodes(
            DefaultTreeModel model,
            DefaultMutableTreeNode parent,
            DefaultMutableTreeNode newNode) {
        parent.add(newNode);
        model.nodesWereInserted(parent, new int[]{parent.getChildCount() - 1});
    }
    protected static void describe(DefaultTreeModel model) {
        describe((DefaultMutableTreeNode) model.getRoot(), 0);
    }
    protected static void describe(DefaultMutableTreeNode node, int level) {
        StringBuilder padding = new StringBuilder();
        for (int index = 0; index < level; index++) {
            padding.append("  ");
        }
        System.out.println(padding + "+ " + node);
        padding.append("  ");
        Enumeration<TreeNode> children = node.children();
        while (children.hasMoreElements()) {
            DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) children.nextElement();
            if (childNode.isLeaf()) {
                System.out.println(padding + "- " + childNode);
            } else {
                describe(childNode, level + 1);
            }
        }
    }
}
READ ALSO
How to lazy fetch only parts of the children entity from the parent entity?

How to lazy fetch only parts of the children entity from the parent entity?

I have a class Department that has a child entity Student(Many to one relationship as a Department can have many students List<Student>

18
How to call a method that has a JPanel over multiple instances in Java [on hold]

How to call a method that has a JPanel over multiple instances in Java [on hold]

I'm trying to make multiple objects with of a class (the Tic class), each with its own JPanel with buttons and stuffRight now when I make instances of the class they all add their buttons to the same JFrame

44
How to turn arg or string into User?

How to turn arg or string into User?

I am making a command and I need to get a list of roles for a user, the problem is that an argument is a string and getMember() expects a UserHow do I turn a string into a User or is there just a better way?

19