Search code examples
javaswingjtree

JTree of object type displays some properties of the object but returns the whole object when selected


I have a program that adds questions to a jtree. Each question on the Jtree is of type Question which has 3 properties; name, id and questionText. I want my Jtree to display only the question name but when the node is selected, it should show the questionText in a textbox.

The problem is the Jtree displays the question's name as I want it to but, when I select a node of the tree I get a ClassCastException. This is because of the getUserObject() in my treeSelectionListener method. It gets a String returned by getUserObject() and tries to cast it to a Question class. How do I get the selected String's Question class properties like questionText or id without getUserObject() or is there another way to represent this tree?

Here is my code:

public class Question 
{
 public String name;
 public String id;
 public String qText;  
 public Question(String name,String id, String text) 
 {
        this.name = name;
        this.id = id;
        this.qText = text;
 }

 public String getQuestion()
 { return qText; }

 public String getName()
 { return name;}

 public String getId()
 { return id;}

 public void setQuestionText(String text)
 { qText= text; }

 public void setId(String uid)
 { id = uid;}

 @Override
 public String toString() 
 { return   name; }
}

Parts of the code to create the tree:

public Question rootQ = new Question("Questions", UUID.randomUUID().toString(), "What is your name?");
public DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(rootQ.toString());
public JTree tree = new JTree(rootNode);

initialise(){
 //....other code to initilise
 panel.add(new JScrollPane(tree));
 tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
 tree.setShowsRootHandles(true);
 tree.addTreeSelectionListener(treeMenuClicked);
 tree.setRootVisible(true);
 tree.setVisible(true);
 panel.add(addChild());
}

public TreeSelectionListener treeMenuClicked = new TreeSelectionListener() 
{

public void valueChanged(TreeSelectionEvent e) 
{
    TreePath currentSelection = tree.getSelectionPath();
    if(currentSelection != null){
     DefaultMutableTreeNode currentNode =  (DefaultMutableTreeNode)currentSelection.getLastPathComponent();
     Object nodeInfo = currentNode.getUserObject();
     Question questionText = (Question)nodeInfo;
     txtQuestion.setText(questionText.getQuestion()); 
    }
}};

public JButton addChild()
{
    JButton btnAddChild = new JButton("Add Child");
    btnAddChild.addActionListener(new ActionListener() 
    {
        public void actionPerformed(ActionEvent arg0) 
        {   String userQuestion = txtQuestion.getText();
            TreePath currentSelection = tree.getSelectionPath();
            if (currentSelection != null) {
                Question createdQuestion = new Question(userQuestion,UUID.randomUUID().toString(),userQuestion);
                DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) currentSelection.getLastPathComponent();
                DefaultTreeModel model = ((DefaultTreeModel) tree.getModel());
                DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(createdQuestion.toString());
                currentNode.add(newNode);
                model.nodeStructureChanged(currentNode);
            }
        }});
    btnAddChild.setBounds(609, 374, 117, 47);
    return btnAddChild;
}

Solution

  • Like @Ajay hinted with his comment, instead of

    DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(createdQuestion.toString());
    

    simply do

    DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(createdQuestion);
    

    You are the one currently setting your user objects to Strings, not the API.

    Also, you can get the selected node through tree.getLastSelectedPathComponent() instead of always getting selection path and then calling TreePath.getLastPathComponent().

    public void valueChanged(TreeSelectionEvent e) 
    {
        DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();
        if(currentNode != null){         
            Object nodeInfo = currentNode.getUserObject();
            Question questionText = (Question)nodeInfo;
            txtQuestion.setText(questionText.getQuestion()); 
        }
    }};