禁用JavaFX中的所有父节点,同时保持其所有子节点都可单击
我正在尝试创建一个JavaFX树视图,其中包含复选框树项。我要求禁用所有具有子节点的节点。但是这些节点的所有子节点都应该是可单击的 基本上,如果树项目是一个叶子,它应该被启用并可单击 这是我目前使用的代码。这会禁用带有子节点的节点,但问题是,由于禁用了该节点,我无法访问父节点中的代码禁用JavaFX中的所有父节点,同时保持其所有子节点都可单击,java,javafx,treeview,Java,Javafx,Treeview,我正在尝试创建一个JavaFX树视图,其中包含复选框树项。我要求禁用所有具有子节点的节点。但是这些节点的所有子节点都应该是可单击的 基本上,如果树项目是一个叶子,它应该被启用并可单击 这是我目前使用的代码。这会禁用带有子节点的节点,但问题是,由于禁用了该节点,我无法访问父节点中的代码 public class App extends Application { public static void main( String[] args ) { launch(args); } priv
public class App extends Application
{
public static void main( String[] args )
{
launch(args);
}
private List<Dependant> myList = new ArrayList();
@SuppressWarnings("unchecked")
@Override
public void start(Stage primaryStage) {
CheckBoxTreeItem<String> rootItem = new CheckBoxTreeItem("Root");
final List<CheckBoxTreeItem<String>> treeItems = new ArrayList(6);
for (int i = 0; i < 6; i++) {
CheckBoxTreeItem<String> item = new CheckBoxTreeItem("L0"+i+"");
item.setIndependent(true);
treeItems.add(item);
myList.add(new Dependant("0"+i+"", "type1"));
}
rootItem.getChildren().addAll(treeItems);
rootItem.setExpanded(true);
rootItem.setIndependent(true);
CheckBoxTreeItem<String> rootItem2 = new CheckBoxTreeItem("folder");
final List<CheckBoxTreeItem<String>> treeItems2 = new ArrayList(6);
for (int i = 0; i < 6; i++) {
CheckBoxTreeItem<String> item = new CheckBoxTreeItem("L1"+i+"");
item.setIndependent(true);
treeItems2.add(item);
myList.add(new Dependant("0"+i+"", "type2"));
}
rootItem2.getChildren().addAll(treeItems2);
rootItem2.setIndependent(true);
rootItem.getChildren().set(2,rootItem2);
TreeView tree = new TreeView(rootItem);
tree.setCellFactory((Object item) -> {
final CheckBoxTreeCell<String> cell = new CheckBoxTreeCell();
cell.itemProperty().addListener((obs,s,s1)->{
cell.disableProperty().unbind();
if(s1!=null && !s1.isEmpty()){
BooleanProperty prop = new SimpleBooleanProperty();
prop.set((s1.equals("folder")));
cell.disableProperty().bind(prop);
}
});
return cell;
});
tree.setRoot(rootItem);
StackPane root = new StackPane();
root.getChildren().add(tree);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
}
公共类应用程序扩展应用程序
{
公共静态void main(字符串[]args)
{
发射(args);
}
private List myList=new ArrayList();
@抑制警告(“未选中”)
@凌驾
公共无效开始(阶段primaryStage){
CheckBoxTreeItem rootItem=新的CheckBoxTreeItem(“根”);
最终列表树项=新的ArrayList(6);
对于(int i=0;i<6;i++){
CheckBoxTreeItem=新的CheckBoxTreeItem(“L0”+i+”);
item.setIndependent(true);
添加(项目);
添加(新的依亲亲属(“0”+i+”,“类型1”);
}
rootItem.getChildren().addAll(treeItems);
setExpanded(true);
setIndependent(true);
CheckBoxTreeItem rootItem2=新的CheckBoxTreeItem(“文件夹”);
最终列表treeItems2=新的ArrayList(6);
对于(int i=0;i<6;i++){
CheckBoxTreeItem=新的CheckBoxTreeItem(“L1”+i+”);
item.setIndependent(true);
treeItems2.添加(项目);
添加(新的依亲亲属(“0”+i+”,“类型2”);
}
rootItem2.getChildren().addAll(treeItems2);
rootItem2.setIndependent(true);
getChildren().set(2,rootItem2);
TreeView树=新的TreeView(rootItem);
tree.setCellFactory((对象项)->{
最终CheckBoxTreeCell单元格=新的CheckBoxTreeCell();
cell.itemProperty().addListener((obs、s、s1)->{
cell.disableProperty().unbind();
如果(s1!=null&&!s1.isEmpty()){
BooleanProperty prop=新的SimpleBoleanProperty();
属性集((s1等于(“文件夹”));
cell.disableProperty().bind(prop);
}
});
返回单元;
});
tree.setRoot(rootItem);
StackPane root=新的StackPane();
root.getChildren().add(树);
原始阶段。设置场景(新场景(根,300250));
primaryStage.show();
}
}
这不是我的应用程序的最终代码,它只是一个示例代码,我在执行最终实现之前试用过
从代码中可以看到,单元格的disabled属性绑定到名称是否等于“folder”,因为方法isLeaf()
不可用
如果有人想知道为什么我需要禁用所有父节点,那是因为在最终实现中,我只需要在整个树视图中选择一个项(因为单击父节点也会选择其所有子节点!)
谢谢。虽然这个问题是一个典型的问题(要求解决一个通过尝试以错误的方式解决实际需求而引入的问题),但真正的问题非常有趣,可以快速尝试:) 根据我的理解,真正的要求是:
- 有一个包含允许选择的项目的树(通过复选框)
- 任何时候只允许选择单个项目
- 实现作为切换的自定义TreeItem(下面的示例扩展了CheckBoxTreeItem)
- 在应用程序代码中,使用该项并根据需要将其添加到ToggleGroups
公共类树SingleSelectedCheckboxWithToggle扩展应用程序{
/**
*实现切换的自定义CheckBoxTreeItem。
*
*控制在任何时间可以选择哪些/多少项
*时间,将它们添加到一个或多个切换组。
*
*@作者Jeanette Winzenburg,柏林
*/
公共静态类ToggleTreeItem扩展了CheckBoxTreeItem
机具切换{
公共开关TreeItem(){
超级();
init();
}
公共切换树项(T值){
超级(价值);
init();
}
私有void init(){
//基本上c&p从切换按钮开始
selectedProperty().addListener(ov->{
最终选定布尔值=isSelected();
最终切换组tg=getToggleGroup();
//注意:这些更改需要在选择Toggle/clearSelectedToggle之前完成,因为
//这些操作会更改属性并可以执行用户代码,可能会再次修改所选属性
如果(tg!=null){
如果(选定){
tg.selectToggle(ToggleTreeItem.this);
}else if(tg.getSelectedToggle()==ToggleTreeItem.this){
//对包专用api的反射访问-使用您自己的实用程序方法
FXUtils.invokeMethod(ToggleGroup.class,tg,“clearSelectedToggle”);
//tg.clearSelectedToggle();
}
}
});
}
/**
*此{@code-ToggleButton}所属的{@link-ToggleGroup}。A
*{@code ToggleButton}在任何时候只能在一个组中。如果
*更改组后,按钮将在更改之前从旧组中删除
*正在添加到新组中。
*/
public class TreeSingleSelectedCheckboxWithToggle extends Application {
/**
* A custom CheckBoxTreeItem that implements Toggle.
*
* To control which/how many items can be selected at any
* time, add them to one or several ToggleGroups.
*
* @author Jeanette Winzenburg, Berlin
*/
public static class ToggleTreeItem<T> extends CheckBoxTreeItem<T>
implements Toggle {
public ToggleTreeItem() {
super();
init();
}
public ToggleTreeItem(T value) {
super(value);
init();
}
private void init() {
// basically c&p from ToggleButton
selectedProperty().addListener(ov -> {
final boolean selected = isSelected();
final ToggleGroup tg = getToggleGroup();
// Note: these changes need to be done before selectToggle/clearSelectedToggle since
// those operations change properties and can execute user code, possibly modifying selected property again
if (tg != null) {
if (selected) {
tg.selectToggle(ToggleTreeItem.this);
} else if (tg.getSelectedToggle() == ToggleTreeItem.this) {
// reflective access to package-private api - use your own utility method
FXUtils.invokeMethod(ToggleGroup.class, tg, "clearSelectedToggle");
// tg.clearSelectedToggle();
}
}
});
}
/**
* The {@link ToggleGroup} to which this {@code ToggleButton} belongs. A
* {@code ToggleButton} can only be in one group at any one time. If the
* group is changed, then the button is removed from the old group prior to
* being added to the new group.
*/
private ObjectProperty<ToggleGroup> toggleGroup;
@Override
public final void setToggleGroup(ToggleGroup value) {
toggleGroupProperty().set(value);
}
@Override
public final ToggleGroup getToggleGroup() {
return toggleGroup == null ? null : toggleGroup.get();
}
@Override
public final ObjectProperty<ToggleGroup> toggleGroupProperty() {
if (toggleGroup == null) {
toggleGroup = new ObjectPropertyBase<ToggleGroup>() {
private ToggleGroup old;
@Override protected void invalidated() {
final ToggleGroup tg = get();
if (tg != null && !tg.getToggles().contains(ToggleTreeItem.this)) {
if (old != null) {
old.getToggles().remove(ToggleTreeItem.this);
}
tg.getToggles().add(ToggleTreeItem.this);
} else if (tg == null) {
old.getToggles().remove(ToggleTreeItem.this);
}
old = tg;
}
@Override
public Object getBean() {
return ToggleTreeItem.this;
}
@Override
public String getName() {
return "toggleGroup";
}
};
}
return toggleGroup;
}
@Override
public Object getUserData() {
// TODO Auto-generated method stub
return null;
}
@Override
public void setUserData(Object value) {
// TODO Auto-generated method stub
}
@Override
public ObservableMap<Object, Object> getProperties() {
// TODO Auto-generated method stub
return null;
}
}
@SuppressWarnings("unchecked")
@Override
public void start(Stage primaryStage) {
ToggleGroup toggleGroup = new ToggleGroup();
ToggleTreeItem<String> rootItem = new ToggleTreeItem<>("Root");
toggleGroup.getToggles().add(rootItem);
final List<ToggleTreeItem<String>> treeItems = new ArrayList<>(6);
for (int i = 0; i < 6; i++) {
ToggleTreeItem<String> item = new ToggleTreeItem<>("L0" + i + "");
item.setIndependent(true);
treeItems.add(item);
toggleGroup.getToggles().add(item);
myList.add(new Dependant("0" + i + "", "type1"));
}
rootItem.getChildren().addAll(treeItems);
rootItem.setExpanded(true);
rootItem.setIndependent(true);
ToggleTreeItem<String> rootItem2 = new ToggleTreeItem<>("folder");
toggleGroup.getToggles().add(rootItem2);
final List<ToggleTreeItem<String>> treeItems2 = new ArrayList<>(6);
for (int i = 0; i < 6; i++) {
ToggleTreeItem<String> item = new ToggleTreeItem<>("L1" + i + "");
item.setIndependent(true);
treeItems2.add(item);
toggleGroup.getToggles().add(item);
myList.add(new Dependant("0" + i + "", "type2"));
}
rootItem2.getChildren().addAll(treeItems2);
rootItem2.setIndependent(true);
rootItem.getChildren().set(2, rootItem2);
TreeView tree = new TreeView<>(rootItem);
tree.setCellFactory(CheckBoxTreeCell.forTreeView());
tree.setRoot(rootItem);
StackPane root = new StackPane();
root.getChildren().add(tree);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
public static class Dependant {
String one;
String two;
public Dependant(String one, String two) {
this.one = one;
this.two = two;
}
}
private List<Dependant> myList = new ArrayList();
public static void main(String[] args) {
launch(args);
}
}