I noticed that listener on selected items within TreeView calls 'onChanged' with strange state.
This problem appears when javafx.scene.control.SelectionMode.MULTIPLE is used.
I attached sample application which allows to reproduce problem.
Case 1:
- select items: 'Item 1' and 'Item 2'
- collapse node: 'Root Node 1'
output >>
[null]
[]
[TreeItem [ value: Root Node 1 ]]
Listener added to observable list: MultipleSelectionModel.getSelectedItems() is called three times. First call contains one 'null' element selected, I don't know why. Selected elements are obtained using ListChangeListener.Change.getList() which, according to the JavaDoc can be always called.
Case 2 - I suppose it may be another form of first case:
- select items: 'Item 21' and 'Item 22'
- collapse node 'Item 2'
output>>
[TreeItem [ value: Root Node 2 ]]
[]
[TreeItem [ value: Item 2 ]]
In this case, 'null' was replaced by TreeItem 'Root Node 2'. Listener informs that this item was selected, but it wasn't in this case.
Sample application:
package treeSelectionProblem;
import javafx.application.Application;
import javafx.collections.ListChangeListener;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class SelectionProblem extends Application {
@Override
public void start(final Stage primaryStage) throws Exception {
final VBox box = new VBox();
final Scene scene = new Scene(box);
primaryStage.setScene(scene);
box.getChildren().add(getTreeView());
primaryStage.show();
}
private Node getTreeView() {
final TreeItem<String> treeItem2 = new TreeItem<String>("Item 2");
treeItem2.getChildren().addAll(new TreeItem<String>("Item 21"), new TreeItem<String>("Item 22"));
final TreeItem<String> root1 = new TreeItem<String>("Root Node 1");
root1.getChildren().addAll(new TreeItem<String>("Item 1"), treeItem2, new TreeItem<String>("Item 3"));
root1.setExpanded(true);
final TreeItem<String> root2 = new TreeItem<String>("Root Node 2");
final TreeItem<String> hiddenRoot = new TreeItem<String>("Hidden Root Node");
hiddenRoot.getChildren().add(root1);
hiddenRoot.getChildren().add(root2);
final TreeView<String> treeView = new TreeView<String>(hiddenRoot);
treeView.setShowRoot(false);
treeView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
// listener which prints selected items
treeView.getSelectionModel().getSelectedItems().addListener(new ListChangeListener<TreeItem<String>>() {
@Override
public void onChanged(final ListChangeListener.Change<? extends javafx.scene.control.TreeItem<String>> c) {
System.out.println(c.getList());
}
});
return treeView;
}
public static void main(final String[] args) {
launch(args);
}
}
This problem appears when javafx.scene.control.SelectionMode.MULTIPLE is used.
I attached sample application which allows to reproduce problem.
Case 1:
- select items: 'Item 1' and 'Item 2'
- collapse node: 'Root Node 1'
output >>
[null]
[]
[TreeItem [ value: Root Node 1 ]]
Listener added to observable list: MultipleSelectionModel.getSelectedItems() is called three times. First call contains one 'null' element selected, I don't know why. Selected elements are obtained using ListChangeListener.Change.getList() which, according to the JavaDoc can be always called.
Case 2 - I suppose it may be another form of first case:
- select items: 'Item 21' and 'Item 22'
- collapse node 'Item 2'
output>>
[TreeItem [ value: Root Node 2 ]]
[]
[TreeItem [ value: Item 2 ]]
In this case, 'null' was replaced by TreeItem 'Root Node 2'. Listener informs that this item was selected, but it wasn't in this case.
Sample application:
package treeSelectionProblem;
import javafx.application.Application;
import javafx.collections.ListChangeListener;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class SelectionProblem extends Application {
@Override
public void start(final Stage primaryStage) throws Exception {
final VBox box = new VBox();
final Scene scene = new Scene(box);
primaryStage.setScene(scene);
box.getChildren().add(getTreeView());
primaryStage.show();
}
private Node getTreeView() {
final TreeItem<String> treeItem2 = new TreeItem<String>("Item 2");
treeItem2.getChildren().addAll(new TreeItem<String>("Item 21"), new TreeItem<String>("Item 22"));
final TreeItem<String> root1 = new TreeItem<String>("Root Node 1");
root1.getChildren().addAll(new TreeItem<String>("Item 1"), treeItem2, new TreeItem<String>("Item 3"));
root1.setExpanded(true);
final TreeItem<String> root2 = new TreeItem<String>("Root Node 2");
final TreeItem<String> hiddenRoot = new TreeItem<String>("Hidden Root Node");
hiddenRoot.getChildren().add(root1);
hiddenRoot.getChildren().add(root2);
final TreeView<String> treeView = new TreeView<String>(hiddenRoot);
treeView.setShowRoot(false);
treeView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
// listener which prints selected items
treeView.getSelectionModel().getSelectedItems().addListener(new ListChangeListener<TreeItem<String>>() {
@Override
public void onChanged(final ListChangeListener.Change<? extends javafx.scene.control.TreeItem<String>> c) {
System.out.println(c.getList());
}
});
return treeView;
}
public static void main(final String[] args) {
launch(args);
}
}