This discussion is archived
4 Replies Latest reply: Dec 20, 2012 3:11 PM by 981131 RSS

Need help making Dynamic Tree Items

971758 Newbie
Currently Being Moderated
The short story is I have decided that a Treeview would be best suited for a properties window I am designing as part of a larger project. I am trying to think of a way to dynamically add TreeItems to the Tree at the click of a a button.(inside an action event block basically) But the API gives some fairly uninspired and static ways to use it. It assumes that the tree is only made right before it is displayed and all the items are static or read from a file before the tree is initialized there does not appear to be an obvious way to add TreeItems to the TreeView after it is made.
Here is what the API shows in its example:

(http://docs.oracle.com/javafx/2/api/index.html)

TreeItem<String> root = new TreeItem<String>("Root Node");
root.setExpanded(true);
root.getChildren().addAll(
new TreeItem<String>("Item 1"),
new TreeItem<String>("Item 2"),
new TreeItem<String>("Item 3")
);
TreeView<String> treeView = new TreeView<String>(root);



Again its only made at the end. I need a way to add TreeItems on the Fly(in response to an event).


I am using an .fxml, a java controller for it, and Netbeans. If that helps.
  • 1. Re: Need help making Dynamic Tree Items
    James_D Guru
    Currently Being Moderated
    You can call
    treeItem.getChildren().add(...);
    or
    treeItem.getChildren().remove(...);
    or indeed any other methods that manipulate the contents of the list of tree items at any time from the FX application thread.

    So for example:

    TreeExample.fxml:
    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.layout.BorderPane?>
    <?import javafx.scene.control.TreeView?>
    <?import javafx.scene.control.TreeItem?>
    <?import javafx.scene.layout.HBox?>
    <?import javafx.scene.control.Button?>
    
    <BorderPane xmlns:fx="http://javafx.com/fxml" fx:controller="TreeExampleController">
         <center>
              <TreeView fx:id="tree">
                <root>
                     <TreeItem value="Root"/>
                </root>
              </TreeView>
         </center>
         <bottom>
              <HBox>
                   <Button text="Add" onAction="#addNode" fx:id="addButton"/>
                   <Button text="Remove" onAction="#removeNode" fx:id="removeButton"/>
              </HBox>
         </bottom>
    </BorderPane>
    TreeExampleController.java:
    import javafx.beans.binding.BooleanBinding;
    import javafx.fxml.FXML;
    import javafx.scene.control.Button;
    import javafx.scene.control.TreeItem;
    import javafx.scene.control.TreeView;
    
    
    public class TreeExampleController {
      private @FXML TreeView<String> tree ;
      private @FXML Button addButton ;
      private @FXML Button removeButton ;
      
      private int count ;
      
      public void initialize() {
        removeButton.disableProperty().bind(new BooleanBinding() {
          {
            super.bind(tree.getSelectionModel().selectedItemProperty());
          }
          @Override
          protected boolean computeValue() {
            TreeItem<String> selectedNode = tree.getSelectionModel().getSelectedItem();
            return selectedNode == null || selectedNode == tree.getRoot();
          }
          
        });
        count = 1 ;
      }
      
      public void addNode() {
        TreeItem<String> parent = tree.getSelectionModel().getSelectedItem();
        if (parent==null) {
          parent = tree.getRoot();
        }
        count++ ;
        final TreeItem<String> newNode = new TreeItem<String>("Node "+count);
        parent.getChildren().add(newNode);
        parent.setExpanded(true);
        tree.getSelectionModel().select(newNode);
      }
      
      public void removeNode() {
        TreeItem<String> selectedNode = tree.getSelectionModel().getSelectedItem();
        if (selectedNode != null) {
          TreeItem<String> parentNode = selectedNode.getParent();
          if (parentNode != null) {
            parentNode.getChildren().remove(selectedNode);
          }
        }
      }
    }
    and TreeExample.java:
    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    
    
    public class TreeExample extends Application {
    
      @Override
      public void start(Stage primaryStage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("TreeExample.fxml"));
        Scene scene = new Scene(root, 600, 400);
        primaryStage.setScene(scene);
        primaryStage.sizeToScene();
        primaryStage.show();
      }
    
      /**
       * @param args
       */
      public static void main(String[] args) {
        launch(args);
      }
    
    }
    Select nodes and add children or remove to your heart's content...
  • 2. Re: Need help making Dynamic Tree Items
    971758 Newbie
    Currently Being Moderated
    hmmnm this approach doesn't seem to work either

     
    
    TreeItem<String> root = new TreeItem<String>("Root Node");
     root.setExpanded(true);
     root.getChildren().addAll(
         new TreeItem<String>("Item 1"),
         new TreeItem<String>("Item 2"),
         new TreeItem<String>("Item 3")
     );
     TreeView<String> properties = new TreeView<String>(root);
    
    TreeItem<String> newtreeitem=new TreeItem<String>(Integer.toString(fpcount),root);
    netbeans really hates that last line. supposedly the constructor for TreeItem can handle a String and Node.
  • 3. Re: Need help making Dynamic Tree Items
    971758 Newbie
    Currently Being Moderated
    Thank you so much. I just figured it out about the time you posted.
  • 4. Re: Need help making Dynamic Tree Items
    981131 Newbie
    Currently Being Moderated
    Hello People.

    I found this thread super helpful to lead me in the right direction to discover how to get around a problem that I was encountering:

    The problem was with these commands, which were not doing their job when executed within the FXML controller:
    TreeItem<String> treeTopLevel = new TreeItem<> ("Inbox");
    TreeView<String> tree = new TreeView<> (treeTopLevel);

    The tree's root entry was not being generated ... and I spent all day trying to figure out why it wasn't working.
    The weird thing is that in hard coded java (with no FXML setup), these lines worked just fine. It's weird. I am using Java7u10.

    The good news is that this route can be circumvented by adding the root to the tree a different way. Here's how:

    private @FXML TreeView<String> tree; // Class variable declared in the controller class

    (in the initialize method ...)
    TreeItem<String> root = new TreeItem<>("Root");
    root.setExpanded(true);
    tree.setRoot(root);

    This sets the TreeItem object directly to the tree object as it's root. I know this is super simple, but I took all day to find it and finally found the method in javadoc. There was no mention of this on the web in examples ... and I must have looked at dozens. So I thought it would be a good idea to post it here to save headaches for others. I hope it helps.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points