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); 
    } 
} 

コードは以下の出力を発生するように:

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

(selectedIndexの、removeIndex)は(3,4)に変更された場合は、その後、出力は次のようになる。

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

選択したインデックスに変更はありません。

実際、限られたテストケースでは、selectedIndexがremoveIndex以下である限り、removeアクションは選択を変更しません。それ以外の場合は、選択が変更されます。

なぜこのように起こりますか?この問題を回避する方法はありますか?

答えて

1

これはJavaのバグです。私はbugs.java.comに報告しました。現在はJDK-8193442と表示されていますが、現在は修正されていません。

回避策は、TreeItemを削除する前にselectedItemを保存し、削除後にselectを呼び出すことです。ただし、selectedItemPropertyのchangelistenerを監視する必要があります。

+0

注意:選択モデルの実装は最適ではありません!明るい側:彼らは改善しています...ゆっくりと)あなたのものはhttps://bugs.openjdk.java.net/browse/JDK-8187596(これはTreeViewに対して報告されました)に関連している可能性があります – kleopatra

+0

@kleopatraこれら2つバグはかなり似ています。彼らは関連する可能性があります。 – 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"]のような配列として表示されます。

このツリーから削除すると、この(おそらく架空の)配列からも削除されます。あなたは何かを削除します。それより大きなインデックスを持つものはすべて1つ下に移動します。

これを処理するには、アイテムを削除した後にselectIndexを適切に更新して新しいインデックスと一致させるためのチェックを行うだけです。あなたは次のような何かをすることができます:

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

プログラムでは、行4にある「Sub Node 0-2」に元の選択があります。「Node 3」は行10にあります。depth-first引数が機能する場合は、「Node 3」を削除する必要があります"Sub Node 0-2"の選択に影響を与えません。 – Guangliang

関連する問題