2017-01-19 13 views
1

TreeTableビューの選択変更にリスナーを適用したいとします。とにかくその行動は期待どおりではありません。ここでJavaFX:TreeTableView Selection Listener予期しない動作

は私のデータモデルである:私は私は私は1つのアイテムを選択するたびに、他のすべてがautomiticallyであることを期待するtreeTable.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);を定義しているので

import javafx.application.Application; 
import javafx.collections.ListChangeListener; 
import javafx.scene.Scene; 
import javafx.scene.control.SelectionMode; 
import javafx.scene.control.TreeItem; 
import javafx.scene.control.TreeTableColumn; 
import javafx.scene.control.TreeTableView; 
import javafx.scene.control.cell.TreeItemPropertyValueFactory; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 

public class treeTableViewTest extends Application { 
    @Override 
    public void start(final Stage stage) { 

     // DemoData ========================================================= 
     File rootFile = new File("/"); 
     TreeItem<File> child2 = new TreeItem<File>(new File("Child 2")); 

     TreeItem<File> root = new TreeItem<File>(rootFile); 
     root.getChildren().add(new TreeItem<File>(new File("Child 1"))); 
     root.getChildren().add(child2); 
     root.getChildren().add(new TreeItem<File>(new File("Child 3"))); 
     root.getChildren().add(new TreeItem<File>(new File("Child 4"))); 
     root.getChildren().add(new TreeItem<File>(new File("Child 5"))); 
     root.setExpanded(true); 
     child2.getChildren().add(new TreeItem<File>(new File("SubChild 1"))); 
     child2.getChildren().add(new TreeItem<File>(new File("SubChild 2"))); 

     // Layout ========================================================= 
     final StackPane stackPane = new StackPane(); 
     TreeTableView<File> treeTable = new TreeTableView<>(); 

     treeTable.setEditable(true); 
     treeTable.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); 
     treeTable.getSelectionModel().setCellSelectionEnabled(false); 
     treeTable.setRoot(root); 

     TreeTableColumn<File,String> fileNameCol = new TreeTableColumn<>("Filename"); 
     treeTable.getColumns().setAll(fileNameCol); 
     fileNameCol.setCellValueFactory(new TreeItemPropertyValueFactory("name")); 

     stackPane.getChildren().add(treeTable); 
     stage.setScene(new Scene(stackPane,250,250)); 
     stage.show(); 

     // Selection Listener ================================================ 

     treeTable.getSelectionModel().getSelectedItems().addListener(new ListChangeListener<TreeItem<File>>() { 

     @Override 
     public void onChanged(ListChangeListener.Change<? extends TreeItem<File>> c) { 
      while (c.next()) { 
       if (c.wasPermutated()) { 
         for (int i = c.getFrom(); i < c.getTo(); ++i) { 
           //permutate 
         } 
        } else if (c.wasUpdated()) { 
          System.out.println("updated: " + c.toString()); 
        } else { 
         for (TreeItem<File> remitem : c.getRemoved()) { 
          System.out.println("removed: " + remitem.toString()); 
         } 
         for (TreeItem<File> additem : c.getAddedSubList()) { 
          System.out.println("added: " + additem.toString()); 
         } 
        } 
       for(TreeItem<File> file : c.getList()){ 
        System.out.println(" -> " + file.toString()); 
       } 
      } 
     }}); 

    // Random Interactions ========================================================= 
      treeTable.getSelectionModel().select(3); 
      treeTable.getSelectionModel().select(5); 
      treeTable.getSelectionModel().clearAndSelect(1); 

    } 

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

import javafx.beans.property.SimpleStringProperty; 
import javafx.beans.property.StringProperty; 
public class File { 
    private StringProperty name = new SimpleStringProperty(this, "name"); 
    public File (String name)   {nameProperty().set(name); } 
    public StringProperty nameProperty() {return this.name; } 
    @Override public String toString() {return name.get().toString() ;} 
} 

そしてここでは、私のメインのアプリケーションです選択解除されます。

私のコードの出力は次のとおりです。

added: TreeItem [ value: Child 3 ] 
    -> TreeItem [ value: Child 3 ] 
added: TreeItem [ value: Child 5 ] 
    -> TreeItem [ value: Child 5 ] 
removed: TreeItem [ value: Child 5 ] 
added: TreeItem [ value: Child 1 ] 
    -> TreeItem [ value: Child 1 ] 

私はこの出力を期待しているでしょう:

added: TreeItem [ value: Child 3 ] 
    -> TreeItem [ value: Child 3 ] 
removed: TreeItem [ value: Child 3 ] // <- missing in original output 
added: TreeItem [ value: Child 5 ] 
    -> TreeItem [ value: Child 5 ] 
removed: TreeItem [ value: Child 5 ] 
added: TreeItem [ value: Child 1 ] 
    -> TreeItem [ value: Child 1 ] 

なぜリスナーで見削除Child 3ないdirectyはありますか?明らかにそれはc.getList()にもうなかったので削除されました。

編集

問題は、今ここにバグ報告として堤出される: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8175260

答えて

1

残念ながら、それは(それがTreeTableViewArrayListSelectionModelである)この選択モデルがどのように動作するかではありません。

ObservableListているにもかかわらず、selectedItemsプロパティは常にその変更について通知されません(任意の通知を提供しません。それはReadOnlyUnbackedObservableListで実装されている - それはそれらを作成し、放出するものを選択モデルです)。

SelectionMode == SINGLEの場合、選択モデルは、ほとんどの場合、quietClearSelectionを実行します。これは、オブザーバーにその事実を知らさずにすべての選択項目を削除するだけです。

なぜ、手動で行をクリックすると正しく動作するのですか? 行をマウスでクリックした後にどのメソッドが呼び出されたかを確認しました。SelectionMode.SINGLEの場合は常にclearAndSelectメソッドです。

選択モデルがSINGLEの場合、すべての「ユーザー」が別の行を選択する前に選択をクリアする必要があります(2つ以上の行を選択すると違法となるため)。私の意見で

SINGLE選択モデルで、あなたはselectedItem財産を守る必要があります - あなたが作業例を見つけることができるの下には:

treeTable.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<TreeItem<File>>() { 
    @Override 
    public void changed(ObservableValue<? extends TreeItem<File>> observable, TreeItem<File> oldValue, TreeItem<File> newValue) { 
     System.out.println(oldValue + "->" + newValue); 
    } 
}); 
+0

が明らかとcoprehensive、について説明、マチェイいただきありがとうございます。 – BerndGit

+0

私の完全なコード(この小さな例ではありません)では、似たような、しかし同じではない、奇妙な振る舞いを見つけました:https://stackoverflow.com/questions/27830075/javafx-exception-when-clicking-treetablecell-after-repopulating-treetableview/28716773 - (あなたの提案にリスナーを変更した後でも)テーブルroot/dataの各更新時に 'table.getSelectionModel()。clearSelection();'を適用して解決することができました。 selctionモデルはここで少し敏感だと思われます。 – BerndGit

+1

問題はOracleにバグ・レポートとして提出されました。http://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8175260 – BerndGit