1

I have a jTree which I populate the nodes from a toString method of List of objects. I have about 10 different kind of objects in that List.

I'm having problems with changing the node name. Normally, when I need to reach an object of a node, I search for the node.toString() in the List to find out where is the object located in the list, so I can do myList.get(i). But when I change the node name, it won't find anything in the List because it doesn't update the objects name. And I can't find a way to save the old name prior to changing node name.

I also tried using my objects as UserObject of the node but when I edit the name, it converts the UserObject back to String

How should I continue?

cbt
  • 1,271
  • 1
  • 11
  • 20
  • Don't rely on `toString`, rely more on something like `DefaultMutableTreeNode`'s `userObject` property and pass the actual object from the list to it, this way you can use the actualy object reference between the two components. Then rely on `JTree`'s custom rendering to render the actual value you want displayed on the screen. Take a closer look at [How to Use Trees](http://docs.oracle.com/javase/tutorial/uiswing/components/tree.html) for more details – MadProgrammer Jan 15 '14 at 23:24
  • @MadProgrammer I did take a look, but I can't seem to understand what happens to a node when I start editing it from the UI. When I 3-click and give it a new name, it changes its userobject to String again. – cbt Jan 15 '14 at 23:30
  • For [example](http://stackoverflow.com/a/11113648/230513). – trashgod Jan 16 '14 at 00:22
  • After some digging around, when a node value is changed the `TableModel#valueForPathChanged` method is called, which sets the nodes user object. You have (at least) two choices. Supply as a custom editor that knows how to edit the original object and returns it (with the new "display" value stored within it) or change the `valueForPathChanged` method to work in away that suits your needs. Personally, I'd go for door #1 (custom editor) – MadProgrammer Jan 16 '14 at 00:23
  • @MadProgrammer I should do `MyTreeCellEditor extends DefaultTreeCellEditor` and build it properly and use it, am I correct? – cbt Jan 16 '14 at 00:45
  • If it meets your needs yes. Remember, you should be using the underlying object that is coming from the `JList` – MadProgrammer Jan 16 '14 at 00:45
  • @trashgod in your example you do something like `return new Resource(value);` but I can't do that in my case because I can't create objects, that are held by nodes, on the fly. I need to be doing something like `myObject o = (myObject) node.getUserObject;` and than `o.setName( newlyEditedValue )` – cbt Jan 16 '14 at 00:54
  • Should I use getTreeCellEditorComponent() to get the node that is being edited in my custom TreeCellEditor? If so how will I get to my node? – cbt Jan 16 '14 at 01:20
  • @trashgod As always you are awesome, thanks! I figured it out. – cbt Jan 16 '14 at 04:11

1 Answers1

2

Thanks to everyone, I managed to tackle this (hopefully) last problem with this particular JTree. Here is how I did it from THIS example:

  private static class MyTreeCellEditor extends DefaultTreeCellEditor {

        public MyTreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer) {
            super(tree, renderer);
        }
        Text newText;
        Real newReal;
        Size newSize;
        Integer newInt;
        Boolean newBool;
        Table newTable;

        @Override
        public Component getTreeCellEditorComponent(JTree jtree, Object o, boolean bln, boolean bln1, boolean bln2, int i) {
            return super.getTreeCellEditorComponent(jtree, o, bln, bln1, bln2, i); //To change body of generated methods, choose Tools | Templates.
        }

    @Override
    public Object getCellEditorValue() {
        String value = (String) super.getCellEditorValue();
        DefaultMutableTreeNode testNode = (DefaultMutableTreeNode) super.tree.getLastSelectedPathComponent();

        Object objToChange = testNode.getUserObject();

        while (objToChange instanceof DefaultMutableTreeNode) {
            DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) objToChange;
            objToChange = parentNode.getUserObject();
        }

        if (testNode.getChildCount() > 0) {
            value += " (" + testNode.getChildCount() + ")";
        }

        if (objToChange instanceof Text) {
            newText = (Text) objToChange;
            newText.setName(value);
            return newText;
        } else if (objToChange instanceof Real) {
            newReal = (Real) objToChange;
            newReal.setName(value);
            return newReal;
        } else if (objToChange instanceof Size) {
            newSize = (Size) objToChange;
            newSize.setName(value);
            return newSize;
        } else if (objToChange instanceof Integer) {
            newInt = (Integer) objToChange;
            newInt.setName(value);
            return newInt;
        } else if (objToChange instanceof Boolean) {
            newBool = (Boolean) objToChange;
            newBool.setName(value);
            return newBool;
        } else if (objToChange instanceof Table) {
            newTable = (Table) objToChange;
            newTable.setName(value);
            return newTable;
        } else {
            return new Text("unexpected object 02");
        }
    }

Text, Real, Size etc. are my custom objects that populate the nodes.

Edit: Just noticed that Object objToChange = testNode.getUserObject(); might return a TreeNode. So I've put a while loop for that.

Community
  • 1
  • 1
cbt
  • 1,271
  • 1
  • 11
  • 20