JavaFX 8 TreeView showing CheckBoxTreeItem with custom CheckBoxTreeCell - checkbox selection issue

I have a weird problem selecting a checkbox with nodes that have children in JavaFX 8 TreeView using CheckBoxTreeItems with a custom CheckBoxTreeCell.

The problem is that the checkboxes for nodes with children must be double-clicked instead of one for selection. Leaves require just one click.

My CheckBoxTreeItems objects accept Person objects. I am overriding the updateItem () method in my CheckBoxTreeCells to set the value displayed to the Person name in TreeCell. If I don't call setText () in my overridden UpdateItem method, TreeCell displays the default myString toString () method (which is not what I want), and all nodes behave as expected when their checkboxes are selected.

I don't want to change the default value of toString in the Person class, so the only workaround I can see is to write a Wrapper class for Person that returns the name Person in its toString (). But I prefer to solve this problem correctly, rather than using a workaround!

Any ideas? Help would be greatly appreciated!

Here is the code I'm using:

class Person {

  String name;

  int age;

  public Person(String name, int age) {
    this.name = name;
    this.age = age;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }
}

and

public class TreeUtilTest extends Application {

  public static void main(String[] args) {
    launch(args);
  }

  @Override
  public void start(Stage primaryStage) throws Exception {
   VBox vBox = new VBox();

   TreeView<Person> treeView = new TreeView<>();
   treeView.setCellFactory(p -> new CheckBoxTreeCell<Person>() {

     @Override
     public void updateItem(Person item, boolean empty) {
        super.updateItem(item, empty);
        if (item != null) {
           setText(item.getName());
        }
     }
    });
   vBox.getChildren().add(treeView);

   CheckBoxTreeItem<Person> treeRoot = new CheckBoxTreeItem<>();
   treeRoot.setValue(new Person("Peter", 10));
   treeRoot.setIndependent(true);
   treeView.setRoot(treeRoot);

   IntStream.range(0, 10).forEach(i -> {
      CheckBoxTreeItem<Person> item = new CheckBoxTreeItem<>();
      item.setValue(new Person("Friend", i));
      item.setIndependent(true);
      treeRoot.getChildren().add(item);
   });


   Scene scene = new Scene(vBox);
   primaryStage.setScene(scene);
   primaryStage.show();
}

}
+4
1

CheckBoxTreeCell , , , ObservableValue<Boolean> StringConverter.

, :

final Callback<TreeItem<Person>, ObservableValue<Boolean>> getSelectedProperty =
        (TreeItem<Person> item) -> {
    if (item instanceof CheckBoxTreeItem<?>) {
        return ((CheckBoxTreeItem<?>)item).selectedProperty();
    }
    return null;
}; 
final StringConverter<TreeItem<Person>> converter = 
        new StringConverter<TreeItem<Person>>() {

    @Override
    public String toString(TreeItem<Person> object) {
        Person item=object.getValue();
        return item.getName();
    }

    @Override
    public TreeItem<Person> fromString(String string) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
};

factory :

treeView.setCellFactory(p -> new CheckBoxTreeCell<>(getSelectedProperty,converter));

, , / , .

, forTreeView, :

treeView.setCellFactory(CheckBoxTreeCell.<Person>forTreeView());

toString Person:

private class Person {
    ...
    @Override
    public String toString() {
        return name;
    }

  }

, : toString , CheckBoxTreeCell:

treeView.setCellFactory(p -> new CheckBoxTreeCell<Person>() {

 @Override
 public void updateItem(Person item, boolean empty) {
    super.updateItem(item, empty);
    if (item != null) {
       setText(item.getName());
    }
 }
});
+6

All Articles