javafx如何禁用checkboxTreeItem中的一个项目?

我是JavaFX的新手,我在复选框树视图中遇到了问题。
我想在根值中禁用一个项目** Serial No但是根据JavaFX文档,似乎不可能。

我已禁用点击效果cbTreeViewdisable(treeItems,3)
有没有办法使任何一个值变灰(或设置一个id),以便用户知道它被禁用。

private TreeView cbTreeView; @Override public void start(Stage primaryStage) { StackPane root = new StackPane(); cbTreeView = new TreeView(); CheckboxTreeItem rootItem = new CheckboxTreeItem("Serial No."); final CheckboxTreeItem[] treeItems = new CheckboxTreeItem[6]; for (int i = 0; i < 6; i++) { treeItems[i] = new CheckboxTreeItem(""+i+""); rootItem.getChildren().addAll(treeItems[i]); } root.setExpanded(true); CheckboxTreeItem rootItem2 = new CheckboxTreeItem("child1"); final CheckboxTreeItem[] treeItems2 = new CheckboxTreeItem[6]; for (int i = 0; i < 6; i++) { treeItems2[i] = new CheckboxTreeItem(""+i+""); rootItem2.getChildren().addAll(treeItems2[i]); } cbTreeView.setRoot(rootItem); cbTreeView.setCellFactory(CheckboxTreeCell.forTreeView()); rootItem.getChildren().set(2,rootItem2); cbTreeViewdisable(treeItems, 3); //rest of code imports css and draws stage which is not relevant to my question } private void cbTreeViewdisable(final CheckboxTreeItem[] treeItems, final int id) { treeItems[id].setIndependent(Boolean.TRUE); treeItems[id].setValue(treeItems[id].getValue().toString()+" Note: you can't select this!)"); treeItems[id].selectedProperty().addListener(new ChangeListener() { @Override public void changed(ObservableValue observable, Boolean oldvalue, Boolean newvalue) { Platform.runLater(new Runnable() { @Override public void run() { treeItems[id].setSelected(Boolean.FALSE); } 

允许禁用树的单个项目的一种方法是将其单元格禁用属性绑定到您可以在运行时修改的外部属性。 为此,当我们设置单元工厂时,我们可以将此绑定添加到单元实现中。 但是我们需要一个引用,所以我们将使用项的值,为了简单起见(这需要唯一的值)。

让我们使用这个pojo:

 class Wrap { public Wrap(String name){ this.name.set(name); this.disabled.set(false); } private final StringProperty name = new SimpleStringProperty(); public String getName() { return name.get(); } public void setName(String value) { name.set(value); } public StringProperty nameProperty() { return name; } private final BooleanProperty disabled = new SimpleBooleanProperty(); public boolean isDisabled() { return disabled.get(); } public void setDisabled(boolean value) { disabled.set(value); } public BooleanProperty disabledProperty() { return disabled; } } 

所以我们可以为树视图上的所有项目创建一个集合:

 private TreeView cbTreeView; private final List disableList = new ArrayList<>(); @Override public void start(Stage primaryStage) { cbTreeView = new TreeView(); CheckBoxTreeItem rootItem = new CheckBoxTreeItem("Serial No."); final List> treeItems = new ArrayList<>(6); for (int i = 0; i < 6; i++) { CheckBoxTreeItem item = new CheckBoxTreeItem("0"+i+""); item.setIndependent(true); treeItems.add(item); disableList.add(new Wrap("0"+i+"")); } rootItem.getChildren().addAll(treeItems); rootItem.setExpanded(true); rootItem.setIndependent(true); CheckBoxTreeItem rootItem2 = new CheckBoxTreeItem("child1"); final List> treeItems2 = new ArrayList<>(6); for (int i = 0; i < 6; i++) { CheckBoxTreeItem item = new CheckBoxTreeItem("1"+i+""); item.setIndependent(true); treeItems2.add(item); disableList.add(new Wrap("1"+i+"")); } rootItem2.getChildren().addAll(treeItems2); rootItem2.setIndependent(true); rootItem.getChildren().set(2,rootItem2); cbTreeView.setRoot(rootItem); 

现在我们创建单元工厂,并在设置项的值时提供绑定:

  cbTreeView.setCellFactory((TreeView item) -> { final CheckBoxTreeCell cell = new CheckBoxTreeCell<>(); cell.itemProperty().addListener((obs,s,s1)->{ cell.disableProperty().unbind(); if(s1!=null && !s1.isEmpty()){ Wrap wrap=disableList.stream() .filter(w->w.getName().equals(s1)) .findFirst().orElse(null); if(wrap!=null){ cell.disableProperty().bind(wrap.disabledProperty()); } } }); return cell; }); 

最后,我们展示了舞台,并禁用了一些随机项:

  Scene scene=new Scene(cbTreeView); primaryStage.setScene(scene); primaryStage.show(); // disable by name disableList.stream() .filter(w->w.getName().equals("03")) .findFirst().ifPresent(w->w.setDisabled(true)); // disable by order disableList.get(7).setDisabled(true); 

}

TreeView与禁用的项目

我想出了扩展CheckBoxTreeItem类的想法。 在那里,我添加了缺少的禁用属性:

 import javafx.beans.property.SimpleBooleanProperty; import javafx.scene.control.CheckBoxTreeItem; public class CheckBoxTreeItemExt extends CheckBoxTreeItem { public SimpleBooleanProperty disabledProperty = new SimpleBooleanProperty(false); public CheckBoxTreeItemExt(T t) { super(t); } public boolean isDisabled() { return disabledProperty.get(); } public void setDisabled(boolean disabled) { disabledProperty.set(disabled); } } 

然后我创建了一个CheckBoxTreeCell,它监听新的disabledProperty:

 import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.scene.control.TreeItem; import javafx.scene.control.cell.CheckBoxTreeCell; public class CheckBoxTreeCellExt extends CheckBoxTreeCell implements ChangeListener { protected SimpleBooleanProperty linkedDisabledProperty; @Override public void updateItem(T item, boolean empty) { super.updateItem(item, empty); if(item != null) { TreeItem treeItem = treeItemProperty().getValue(); if(treeItem != null) { if(treeItem instanceof CheckBoxTreeItemExt) { CheckBoxTreeItemExt checkItem = (CheckBoxTreeItemExt)treeItem; if(checkItem != null) { if(linkedDisabledProperty != null) { linkedDisabledProperty.removeListener(this); linkedDisabledProperty = null; } linkedDisabledProperty = checkItem.disabledProperty; linkedDisabledProperty.addListener(this); setDisable(linkedDisabledProperty.get()); } } } } } @Override public void changed(ObservableValue arg0, Boolean oldVal, Boolean newVal) { setDisable(newVal); } } 

最后我们有了CheckBoxTreeCellFactory:

 import javafx.scene.control.TreeCell; import javafx.scene.control.TreeView; import javafx.util.Callback; public class CheckBoxTreeCellFactoryExt implements Callback, TreeCell> { @Override public TreeCell call(TreeView tv) { return new CheckBoxTreeCellExt(); } } 

非常感谢@Pereda。 如果将root设置为独立,则效果很好。 由于我正在使用Java 7,我替换了代码

 Wrap wrap=disableList.stream() .filter(w->w.getName().equals(s1)) .findFirst().orElse(null); if(wrap!=null){ cell.disableProperty().bind(wrap.disabledProperty()); } 

有了这个

 for (int i = 0; i < disabledList.size();i++) { if (disabledList.get(i).getName().equals(s1)) { cell.disabledProperty.bind(disabledList.get(i).disabledProperty()); } } 

但是如果root 没有被设置为独立的,我点击root并且被禁用的孩子也会得到一个不正确的勾号。 那么这种情况下的解决方案是什么?