1

JavaFX TreeTableView가 있습니다. 루트 아래에 TreeItem (노드) 집합이 있고 각 노드에는 자체 TreeItem (하위 노드)이있을 수 있습니다. 하위 노드가없는 노드에 대해서는 표시 할 정보가 없으므로이를 제거하려고합니다. 그러나 어쨌든 간단한 제거 동작으로 선택을 언젠가 바꿀 수 있습니다.JavaFX TreeItem 제거 가끔 TreeTableView 선택 변경

package sample; 

import javafx.application.Application; 
import javafx.beans.property.ReadOnlyStringWrapper; 
import javafx.scene.Scene; 
import javafx.scene.control.TreeItem; 
import javafx.scene.control.TreeTableColumn; 
import javafx.scene.control.TreeTableView; 
import javafx.stage.Stage; 

public class Main extends Application { 

    @Override 
    public void start(Stage primaryStage) throws Exception{ 
     TreeItem<String> rootNode = new TreeItem<String>("Root"); 
     rootNode.setExpanded(true); 
     rootNode.getChildren().setAll(new TreeItem<>("Node 0"), 
       new TreeItem<>("Node 1"), new TreeItem<>("Node 2"),//); 
       new TreeItem<>("Node 3"), new TreeItem<>("Node 4")); 
     for (int i = 0; i < 2; i++) { 
      TreeItem<String> node = rootNode.getChildren().get(i); 
      node.setExpanded(true); 
      node.getChildren().setAll(new TreeItem<>("Sub Node " + i + "-0"), 
        new TreeItem<>("Sub Node " + i + "-1"), 
        new TreeItem<>("Sub Node " + i + "-2")); 
     } 

     TreeTableColumn<String, String> column = new TreeTableColumn<>("Nodes"); 
     column.setCellValueFactory((TreeTableColumn.CellDataFeatures<String, String> p) -> { 
      return new ReadOnlyStringWrapper(p.getValue().getValue()); 
     }); 
     column.setPrefWidth(200); 

     TreeTableView<String> table = new TreeTableView<>(rootNode); 
     table.getColumns().add(column); 

     int selectIndex = 4; 
     int removeIndex = 3; 
     table.getSelectionModel().select(selectIndex); 
     System.out.println("Selected index = " + table.getSelectionModel().getSelectedIndex()); 
     System.out.println("Selected item = " + table.getSelectionModel().getSelectedItem().getValue()); 
     table.getRoot().getChildren().remove(removeIndex); 
     System.out.println("Selected index = " + table.getSelectionModel().getSelectedIndex()); 
     System.out.println("Selected item = " + table.getSelectionModel().getSelectedItem().getValue()); 

     primaryStage.setTitle("Tree Table View Selection"); 
     primaryStage.setScene(new Scene(table, 300, 275)); 
     primaryStage.show(); 
    } 


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

그 다음 출력 낸다 같이 코드 (selectedIndex의, removeIndex)가 (3,4)로 변경되는 경우

Selected index = 4 
Selected item = Sub Node 0-2 
Selected index = 3 
Selected item = Sub Node 0-1 

그러나, 그 출력이된다 :

Selected index = 3 
Selected item = Sub Node 0-1 
Selected index = 3 
Selected item = Sub Node 0-1 

선택한 인덱스가 변경되지 않았습니다.

실제로 제한된 테스트 케이스에서 selectedIndex가 removeIndex보다 작거나 같은 경우 제거 액션으로 선택 항목이 변경되지 않습니다. 그렇지 않으면 선택을 변경합니다.

왜 이런 식으로 발생합니까? 이 문제를 해결할 수있는 방법이 있습니까?

답변

1

그것은 자바에서 버그입니다. 나는 bugs.java.com에보고했으며, 현재 JDK-8193442으로 나열되어 있으며 현재 아직 수정이 이루어지지 않았습니다.

해결 방법은 TreeItem을 제거하기 전에 selectedItem을 저장하고 제거 후 select를 호출하는 것입니다. 하나는 changelistener를 selectedItemProperty에서 조심해야한다.

+0

주의 : 선택 모델 구현은 ... 최적이 아닙니다! 밝은면에서 : 그들은 천천히 개선되고있다.) 당신의 것은 https://bugs.openjdk.java.net/browse/JDK-8187596 (TreeView에 대해보고 된)과 관련이있을 수있다. – kleopatra

+0

@kleopatra이 두 버그는 꽤 비슷해 보입니다. 그것들은 관련 될 수 있습니다. – Guangliang

0

여기서는 선택 항목이 아니라 선택한 색인이 있고 트리에서 노드를 제거 할 때 선택된 색인은 동일하게 유지되지만 색인의 항목은 이제 다릅니다.

당신의 나무는 당신이 인쇄 한 것을 기준으로 깊이 우선 인덱싱되므로 인덱스 맵의 아이템 맵은 ["Root", "Node 0", "Sub Node 0-0", "Sub Node 0-1", "Sub Node 0-2", "Node 1", "Sub Node 1-1" ... "Sub Node 4-2"]과 같은 배열로 그려집니다.

이 트리에서 제거하면이 (가상의) 배열에서도 제거됩니다. 당신은 무언가를 제거하고, 그것보다 큰 지수를 가진 모든 것이 한 자리 아래로 이동됩니다.

이 문제를 해결하려면 항목을 제거한 후에 selectIndex를 적절하게 업데이트하여 새 색인과 일치 시키도록하십시오. 당신은 다음과 같은 것을 할 수 있습니다 :

if(selectIndex > removeIndex) 
    selectIndex--; 
+0

프로그램에서 원래 선택은 행 4에있는 "Sub Node 0-2"에 있습니다. "노드 3"은 행 10에 있습니다. 깊이 우선 인수가 작동하면 "노드 3"을 제거해야합니다 "서브 노드 0-2"선택에 영향을 미치지 않습니다. – Guangliang