2017-09-19 1 views
0

CheckBox가있는 노드가 몇 개있는 TreeView가 있습니다 (MWE 참조).TreeView를 축소/확장하면 CheckBox가 무작위로 검사됩니다.

일부 노드를 축소/확장 할 때 다른 노드의 CheckBoxes가 선택되거나 선택 해제됩니다.

문제를 재현하려면 모든 노드를 확장하고 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를 통해 노드의 상태 (체크 여부)를 얻고 싶습니다.

인해 TreeCell이 IndexedCell에서 확장한다는 사실에, 각 TreeCell 또한 인덱스 속성을 제공합니다 https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/TreeCell.html에서

나는 다음 알고있다. 셀이 확장되거나 축소되면 인덱스가 업데이트되므로 모델 인덱스가 아닌 뷰 인덱스로 간주되어야합니다.

이렇게 의도 된 동작입니까? 왜 누군가는 그것을 갖고 싶어 할까?

답변

0

표시되는 동작은 셀의 인덱스와는 아무런 관련이 없지만 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); 
    } 
} 
관련 문제