当前位置: 首页 > 知识库问答 >
问题:

折叠/展开TreeView随机选中复选框

闻人吕恭
2023-03-14

当折叠/展开某个节点时,其他节点的复选框被选中或未选中。

要重现这种行为,只需展开所有节点,检查childa、折叠block1childc将自动检查。

package treeviewexample;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.CheckBoxTreeCell;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;


public class TreeViewExample extends Application {

  @Override
  public void start(Stage primaryStage) {

    StackPane root = new StackPane();

    /* example Treeview */
    TreeView tw = new TreeView();
    TreeItem rootNode = new TreeItem("Root");
    TreeItem blockOne = new TreeItem("Block1");
    TreeItem childA = new TreeItem("ChildA");
    TreeItem childB = new TreeItem("ChildB");
    blockOne.getChildren().add(childA);
    blockOne.getChildren().add(childB);
    TreeItem blockTwo = new TreeItem("Block2");
    TreeItem childC = new TreeItem("ChildC");
    TreeItem childD = new TreeItem("ChildD");
    blockTwo.getChildren().add(childC);
    blockTwo.getChildren().add(childD);
    rootNode.getChildren().add(blockOne);
    rootNode.getChildren().add(blockTwo);
    tw.setRoot(rootNode);

    /* add CheckBoxes */
    tw.setCellFactory(CheckBoxTreeCell.<String>forTreeView());

    root.getChildren().add(tw);
    Scene scene = new Scene(root, 300, 250);
    primaryStage.setTitle("Hello World!");
    primaryStage.setScene(scene);
    primaryStage.show();
  }

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

}

我怎样才能防止这种行为?在稍后的程序中,我希望通过TreeView并获取节点的状态(已选中或未选中)来使用它们。

共有1个答案

秦博达
2023-03-14

您所看到的行为与单元格的索引无关,这完全是因为您没有为CheckBoxTreeCell提供任何机制来“知道”是否应该检查它。因此,当您展开或折叠树中的节点,并且单元格被重用用于其他项时,它们可能会保持其选中状态,即使它们现在应该表示新数据

这里的基本问题是CheckBoxTreeCell只是视图:它不维护所选状态。您需要提供一种机制,让单元格知道它所表示的项是否被选中。API提供了两种实现此目的的方法:使用CheckBoxTreeItem作为树中的项,或者使用具有BooleanProperty的模型类并提供到该布尔属性的映射。

第一个版本看起来是这样的(我也去掉了所有原始类型:您真的不应该在这里发布生成警告的代码,然后忽略它们):

public void start(Stage primaryStage) {

    StackPane root = new StackPane();

    /* example Treeview */
    TreeView<String> tw = new TreeView<>();
    CheckBoxTreeItem<String> rootNode = new CheckBoxTreeItem<>("Root");
    CheckBoxTreeItem<String> blockOne = new CheckBoxTreeItem<>("Block1");
    CheckBoxTreeItem<String> childA = new CheckBoxTreeItem<>("ChildA");
    CheckBoxTreeItem<String> childB = new CheckBoxTreeItem<>("ChildB");
    blockOne.getChildren().add(childA);
    blockOne.getChildren().add(childB);
    CheckBoxTreeItem<String> blockTwo = new CheckBoxTreeItem<>("Block2");
    CheckBoxTreeItem<String> childC = new CheckBoxTreeItem<>("ChildC");
    CheckBoxTreeItem<String> childD = new CheckBoxTreeItem<>("ChildD");
    blockTwo.getChildren().add(childC);
    blockTwo.getChildren().add(childD);
    rootNode.getChildren().add(blockOne);
    rootNode.getChildren().add(blockTwo);
    tw.setRoot(rootNode);

    /* add CheckBoxes */
    tw.setCellFactory(CheckBoxTreeCell.<String>forTreeView());

    root.getChildren().add(tw);
    Scene scene = new Scene(root, 300, 250);
    primaryStage.setTitle("Hello World!");
    primaryStage.setScene(scene);
    primaryStage.show();
} 
@Override
public void start(Stage primaryStage) {

    StackPane root = new StackPane();

    /* example Treeview */
    TreeView<Item> tw = new TreeView<>();
    CheckBoxTreeItem<Item> rootNode = new CheckBoxTreeItem<>(new Item("Root"));
    CheckBoxTreeItem<Item> blockOne = new CheckBoxTreeItem<>(new Item("Block1"));
    CheckBoxTreeItem<Item> childA = new CheckBoxTreeItem<>(new Item("ChildA"));
    CheckBoxTreeItem<Item> childB = new CheckBoxTreeItem<>(new Item("ChildB"));
    blockOne.getChildren().add(childA);
    blockOne.getChildren().add(childB);
    CheckBoxTreeItem<Item> blockTwo = new CheckBoxTreeItem<>(new Item("Block2"));
    CheckBoxTreeItem<Item> childC = new CheckBoxTreeItem<>(new Item("ChildC"));
    CheckBoxTreeItem<Item> childD = new CheckBoxTreeItem<>(new Item("ChildD"));
    blockTwo.getChildren().add(childC);
    blockTwo.getChildren().add(childD);
    rootNode.getChildren().add(blockOne);
    rootNode.getChildren().add(blockTwo);
    tw.setRoot(rootNode);

    StringConverter<TreeItem<Item>> itemStringConverter = new StringConverter<TreeItem<Item>>() {

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

        @Override
        public TreeItem<Item> fromString(String string) {
            return new TreeItem<>(new Item(string));
        }

    };

    /* add CheckBoxes */
    tw.setCellFactory(
            CheckBoxTreeCell.forTreeView(treeItem -> treeItem.getValue().selectedProperty(), itemStringConverter));

    root.getChildren().add(tw);
    Scene scene = new Scene(root, 300, 250);
    primaryStage.setTitle("Hello World!");
    primaryStage.setScene(scene);
    primaryStage.show();
}

public static class Item {

    private final String name;
    // use something with a more meaningful name here:
    private final BooleanProperty selected = new SimpleBooleanProperty();

    public Item(String name, boolean selected) {
        this.name = name;
        setSelected(selected);
    }

    public Item(String name) {
        this(name, false);
    }

    public String getName() {
        return name;
    }

    public BooleanProperty selectedProperty() {
        return selected;
    }

    public final boolean isSelected() {
        return selectedProperty().get();
    }

    public final void setSelected(boolean selected) {
        selectedProperty().set(selected);
    }
}
 类似资料:
  • I',试图构建一个扩展/折叠菜单。 我有一个主导航栏,里面有3个子菜单。默认情况下,子菜单的高度为50px,但一旦点击,这个高度就会变为200px。再点击一下,让它塌陷回原来的50px。 让我烦恼的是,当我展开subMenu1,然后展开Submenu2-Submenu1保持展开,并且我希望它在第二个子菜单被选中时折叠。 这是我的代码; 和jQuery: 我想知道什么功能或什么使用来确保一旦任何子菜

  • 我已展开treeView的某些项 我使用contextMenu向指定节点添加新项目 项已添加到我的结构(后端) 重新加载TreeView-它从一开始就显示(仅根目录) 我想有我的树视图的视图像之前添加项目(这个相同的项目折叠和展开)。我不知道怎么做。我正在考虑改变StructureNode的实现(add boolean field是扩展的并使用它,但它不起作用--我正在从文件中打开我的树视图,那里

  • 本文向大家介绍vue多级复杂列表展开/折叠及全选/分组全选实现,包括了vue多级复杂列表展开/折叠及全选/分组全选实现的使用技巧和注意事项,需要的朋友参考一下 首先,来看下效果图 在线体验地址:https://hxkj.vip/demo/multipleList/。温馨提示,打开之后按F12,使用手机模式食用,口味更佳! 可以看出,这个列表有三种展现形式: 1.第一层级中包含直属子项和第二层级,其

  • 我有一个带有多个视图保持器的RecyclerView适配器。每个ViewHolder都有一个标题TextView和一个嵌套的RecyclerView,工作正常。但我想实现一个扩展/折叠函数,这样嵌套的RecyclerView就可以隐藏,直到单击标题为止。我使用此方法RecyclerView展开/折叠项目。它可以工作,但当我单击标题以展开嵌套的RecyleView时,recyclerview不会填充

  • 展开或折叠代码 操作步骤: 菜单栏:Code —> Folding —> Expand 快捷键: Mac: command + “+” Windows\/Linux: Ctrl + "+" 展开或折叠代码 操作步骤: 菜单栏:Code —> Folding —> Collapse 快捷键: Mac: command + “-” Windows\/Linux: Ctrl + "-" 展开或折叠当前代

  • 问题内容: 我能够展开和折叠单元格,但我想在UITableViewCell内调用函数(展开和折叠)以更改按钮标题。 问题答案: 如果你想在细胞获得更大的身体,那么,你有你的店,在使用: 然后,当您想在didSelectRow中展开一个时: 编辑 这将使单元动画自己变大,您不需要单元中额外的动画块。 编辑2