문제

I have developed an application to search a node in a JTree. Whenever "Get Original Tree" button is clicked the clonedRoot should be populated with the original data. All the processing is performed on the clonedRoot.

Everything is working fine (deducing the console output) except that the updated clonedRoot is not rendered on the panel.

clonedRoot populated with the original data enter image description here

 if(ae.getSource()==getOriginalTree)
        {
            System.out.println("Get original tree");
            System.out.println("Nodes present under cloned Root before deep copying");
            DisplayNodes(clonedRoot);
            getDeepCopy();
             System.out.println("Nodes present under cloned Root after deep copying");
             DisplayNodes(clonedRoot);
             DefaultTreeModel newModel = new DefaultTreeModel(clonedRoot);
             clonedTree.setModel(newModel);
             for (int i = 0; i < clonedTree.getRowCount(); i++)
             {
             clonedTree.expandRow(i);
             }
             System.out.println("Updated tree");
        }

clonedRoot after performing a search operation enter image description here

Console Output on clicking "Get Original Tree"-

    Get original tree

    Nodes present under cloned Root before deep copying  

    A
    A1   

    Cloning done   

    Nodes present under cloned Root after deep copying

    A
    A1
    A2
    A3
    B
    B1
    B2
    B3
    C
    C1
    C2
    C3
    D
    D1
    D2
    D3
    E
    E1
    E2
    E3

    Updated tree


Initialization Code in ctor
{

        root = new DefaultMutableTreeNode("Root");
        tree = new JTree(root);
        setLAF();
        populateTree();
        copyBuilder = new DeepCopyJTreeAlt(tree);
        getDeepCopy();
        System.out.println("Original Tree");
        displayTree(tree);
        System.out.println("Cloned Tree");
        displayTree(clonedTree);
        label = new JLabel("Serach Node");
        field = new JTextField();
        for (int i = 0; i < clonedTree.getRowCount(); i++)
        {
         clonedTree.expandRow(i);
        }
        tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        pane = new JScrollPane(clonedTree);
        centralPanel = new JPanel();
        centralPanel.setLayout(new BorderLayout());
        submit = new JButton("Search");
        submit.addActionListener(new SearchActionListener());
        getOriginalTree = new JButton("Get Original Tree");
        getOriginalTree.addActionListener(new SearchActionListener());
        buttonPanel = new JPanel();
        buttonPanel.setLayout(new GridLayout(0, 4));
        buttonPanel.add(label);
        buttonPanel.add(field);
        buttonPanel.add(submit);
        buttonPanel.add(getOriginalTree);
        centralPanel.add(pane, BorderLayout.CENTER);
        centralPanel.add(buttonPanel, BorderLayout.SOUTH);
        frame = new JFrame();
        frame.add(centralPanel);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600, 500);
        frame.setVisible(true);

    }

    private void populateTree() 
{
        A = addAFile("A", root);
        A1 = addAFile("A1", A);
        A2 = addAFile("A2", A);
        A3 = addAFile("A3", A);
        B = addAFile("B", root);
        B1 = addAFile("B1", B);
        B2 = addAFile("B2", B);
        B3 = addAFile("B3", B);
        C = addAFile("C", root);
        C1 = addAFile("C1", C);
        C2 = addAFile("C2", C);
        C3 = addAFile("C3", C);
        D = addAFile("D", root);
        D1 = addAFile("D1", D);
        D2 = addAFile("D2", D);
        D3 = addAFile("D3", D);
        E = addAFile("E", root);
        E1 = addAFile("E1", E);
        E2 = addAFile("E2", E);
        E3 = addAFile("E3", E);

    }

 private DefaultMutableTreeNode addAFile(String fileName, DefaultMutableTreeNode parentFolder) {

        DefaultMutableTreeNode newFile = new DefaultMutableTreeNode(fileName);

        parentFolder.add(newFile);

        return newFile;
    }
도움이 되었습니까?

해결책

I think you should call a treeModel.reload() after you set the model

if(ae.getSource()==getOriginalTree)
    {
        System.out.println("Get original tree");
        System.out.println("Nodes present under cloned Root before deep copying");
        DisplayNodes(clonedRoot);
        getDeepCopy();
         System.out.println("Nodes present under cloned Root after deep copying");
         DisplayNodes(clonedRoot);
         DefaultTreeModel newModel = new DefaultTreeModel(clonedRoot);
         clonedTree.setModel(newModel);
         newModel.reload();
         for (int i = 0; i < clonedTree.getRowCount(); i++)
         {
         clonedTree.expandRow(i);
         }
         System.out.println("Updated tree");
    }

I've made a simple class that works a bit like what you have. As you can see, after setting the clicking the button, the tree is refreshed with the new model. Since your code is similar, I think that maybe your clonedTree is not displayed correctly, maybe it's not the only tree in the window.

public class JTreeTest extends JPanel {

private static DefaultMutableTreeNode root;

public  static void main(String[] args) {

    JPanel panel = new JPanel(new GridLayout());
    JFrame frame = new JFrame("Test");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setContentPane(panel);
    frame.setSize(400, 400);

    root = new DefaultMutableTreeNode("A");
    DefaultTreeModel model = new DefaultTreeModel(root);
    model.insertNodeInto(new DefaultMutableTreeNode("A1"), root, 0);
    model.insertNodeInto(new DefaultMutableTreeNode("A2"), root, 0);
    model.insertNodeInto(new DefaultMutableTreeNode("A3"), root, 0);

    final JTree tree = new JTree(model);
    tree.setRootVisible(true);
    panel.add(tree);

    JButton refresh = new JButton("Refresh") ;
    panel.add(refresh);
    refresh.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(final ActionEvent e) {
            root = new DefaultMutableTreeNode("B");
            DefaultTreeModel newModel = new DefaultTreeModel(root);
            tree.setModel(newModel);
        }
    });

    frame.setVisible(true);
    }
}

I've put your code in a test class and made the following clone method:

private static void cloneRoot(DefaultMutableTreeNode updatableRoot) {
    updatableRoot.removeAllChildren();
    for (int i = 0; i < root.getChildCount() / 2; i++) {
        updatableRoot.add((javax.swing.tree.MutableTreeNode) root.getChildAt(i));
    }
}

But after some tests I realized a big mistake I was making. The DefaultMutableTreeNode.add() method removes the node from the parent and puts it under the new parent. Do you make a deep copy of your nodes?

A correct method to clone it would be

    private DefaultMutableTreeNode cloneRoot() {
    DefaultMutableTreeNode updatableRoot = new DefaultMutableTreeNode("Root");
    for (int i = 0; i < root.getChildCount(); i++) {
        DefaultMutableTreeNode parent = new DefaultMutableTreeNode(root.getChildAt(i));
        updatableRoot.add(parent);
        Enumeration<DefaultMutableTreeNode> children = root.getChildAt(i).children();
        while (children.hasMoreElements()) {
            parent.add(new DefaultMutableTreeNode(children.nextElement()));
        }
    }
    return updatableRoot;
}

I've found what the problem was. Your getDeepCopy() method looked like this:

    public void getDeepCopy() {
       clonedTree = copyBuilder.cloneTree();
       TreeModel model = clonedTree.getModel();
       clonedRoot = (DefaultMutableTreeNode) model.getRoot();
   }

This means that you were creating a new JTree and assign it to the clonedTree variable each time you were making a copy. By doing this, you were losing the reference to the initial JTree that was created in the constructor and was displayed on the JFrame. I've added below one solution to your problem, by updating the getDeepCopyMethod()

    private void getDeepCopy() {
       final JTree initialTree = copyBuilder.cloneTree();
       final TreeModel model = initialTree.getModel();
       clonedRoot = (DefaultMutableTreeNode) model.getRoot();
       if (clonedTree != null) {
          clonedTree.setModel(model);
       } else {
         clonedTree = initialTree;
       }
    }

Another solution would be to remove clonedTree from the JScrollPane and add it again after you updated it.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top