JTree, setUserObject(), toString()

1.1k views Asked by At

What I'm trying to do is pretty simple, but running into some issues. I have a class and I`m overriding toString() with some value.

public class AClass {

@Override
public String toString() {
    int rand = 5 + (int) (Math.random() * 25);
    return Integer.toString(rand);
    }
}

I have a JTree and I`m adding the class object to the node by using setUserObject(). The display on the node now has the value from toString().

            DefaultMutableTreeNode  node = new DefaultMutableTreeNode();
            node.setUserObject(new AClass());
            fileTreeModel.insertNodeInto(node, (DefaultMutableTreeNode) rootNode, 0);
            tree.setSelectionPath(new TreePath(fileTreeModel.getPathToRoot(node)));
            tree.expandPath(new TreePath(rootNode.getPath()));

But, when I click on the nodes or try to add a new node, the toString() values are changing.

What`s going on here? Any help is greatly appreciated. Here is some sample code.

Main.java

import java.awt.Color;
import java.awt.EventQueue;

import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JSplitPane;

import java.awt.BorderLayout;

import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

import javax.swing.JScrollPane;


public class Main {

private JFrame frame;
private JTree tree;
private DefaultMutableTreeNode rootNode ;
private DefaultTreeModel fileTreeModel;

/**
 * Launch the application.
 */
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                Main window = new Main();
                window.frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the application.
 */
public Main() {
    initialize();
}

/**
 * Initialize the contents of the frame.
 */
private void initialize() {
    frame = new JFrame();
    frame.setBounds(100, 100, 450, 300);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JSplitPane splitPane = new JSplitPane();
    splitPane.setResizeWeight(0.2);
    frame.getContentPane().add(splitPane, BorderLayout.CENTER);

    JScrollPane scrollPane = new JScrollPane();
    splitPane.setLeftComponent(scrollPane);

    tree = new JTree();
    tree.setBackground(new Color(255, 235, 205));
    scrollPane.setViewportView(tree);
    rootNode = new DefaultMutableTreeNode("Files");
    fileTreeModel = new DefaultTreeModel(rootNode);
    tree.setModel(fileTreeModel);
    tree.getSelectionModel().setSelectionMode(
            TreeSelectionModel.SINGLE_TREE_SELECTION);
    tree.setRootVisible(true);

    JDesktopPane desktopPane = new JDesktopPane();
    desktopPane.setBackground(new Color(255, 255, 0));
    splitPane.setRightComponent(desktopPane);

    JButton btnNewButton = new JButton("New button");
    btnNewButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {

            DefaultMutableTreeNode  node = new DefaultMutableTreeNode();
            node.setUserObject(new AClass());
            fileTreeModel.insertNodeInto(node, (DefaultMutableTreeNode) rootNode, 0);
            tree.setSelectionPath(new TreePath(fileTreeModel.getPathToRoot(node)));
            tree.expandPath(new TreePath(rootNode.getPath()));
        }
    });
    btnNewButton.setBounds(122, 115, 89, 23);
    desktopPane.add(btnNewButton);

    }

}

AClass.java

public class AClass {

@Override
public String toString() {
    int rand = 5 + (int) (Math.random() * 25);
    return Integer.toString(rand);
    }

}
1

There are 1 answers

1
MadProgrammer On

They are changing because each time toString is called you are calculating a new random number...

public String toString() {
    int rand = 5 + (int) (Math.random() * 25);
    return Integer.toString(rand);
}

So, each time the table updates, in response to, let's say, you clicking on them, or modifying the TreeModel in some way, the tree asks each node for it's value, which returns a new random number.

Try pre-calculating the value upfront.

node.setUserObject(new AClass(5 + (int) (Math.random() * 25)));

Then simply return this value...

public String toString() {
    return Integer.toString(rand);
}