ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

JavaFX 8 TreeView显示CheckBoxTreeItem与自定义CheckBoxTreeCell – 复选框选择问题

2019-05-28 18:50:27  阅读:1105  来源: 互联网

标签:java checkbox treeview javafx javafx-8


我有一个奇怪的复选框选择问题,使用带有自定义CheckBoxTreeCell的CheckBoxTreeItems,在JavaFX 8 TreeView中具有Children的节点.

问题是必须单击带有子项的节点的复选框两次而不是一次才能被选中.叶子只需要一次点击即可.

我的CheckBoxTreeItems采用Person Objects.我重写了CheckBoxTreeCells中的updateItem()方法,将显示的值设置为TreeCell中Person的名称.如果我没有在我的overcover updateItem方法中调用setText(),TreeCell会显示我的Person对象的默认toString()方法(这不是我想要的),并且所有节点在选择它们的复选框时都会表现出预期的行为.

我不想在Person类中更改默认的toString,所以我看到的唯一解决方法是为Person编写一个Wrapper类,在其toString()中返回Persons名称.但我更愿意正确解决这个问题,而不是使用解决方法!

有任何想法吗?非常感谢帮助!

这是我使用的代码:

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;
  }
}

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();
}

}

解决方法:

如果你看看CheckBoxTreeCell class,你会发现它有可能提供一个返回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.");
    }
};

现在我们只需要使用以下两个参数定义单元工厂:

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

如果您尝试这样做,您将看到只需单击一下即可选择/取消选择根以及子项.

编辑

有一个更简单的解决方案,使用静态方法forTreeView,您不需要提供回调或转换器:

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

但要实现这一点,您只需要在Person中覆盖toString:

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());
    }
 }
});

标签:java,checkbox,treeview,javafx,javafx-8
来源: https://codeday.me/bug/20190528/1173019.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有