Details
-
Bug
-
Resolution: Fixed
-
P3
-
8
-
MacOS X, Java 8 Build 121
Description
In my application I am listening to the expandedItemCountProperty() of TreeTableView. Whenever the value changes I am building up a list of all tree items that are currently visible in the tree table. I am then passing this list to a ListView, so that the rows in the tree table view and the list view are identical. I started noticing that the rows became out of synch after one or two clicks. After some investigation I found out that the method getTreeItem(int index) does not return the correct items for the given indices.
The following program demonstrates the issue. Please pay attention to the output in the console. The problem will manifest itself after expanding / collapsing "group2".
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.scene.control.cell.TreeItemPropertyValueFactory;
import javafx.stage.Stage;
public class TestExpandedItemCountBug extends Application {
@Override
public void start(Stage stage) throws Exception {
final TreeTableView<Person> view = new TreeTableView<>();
view.setPrefSize(300, 500);
TreeItem<Person> root = new TreeItem<>(new Person("Boss"));
view.setRoot(root);
TreeItem<Person> group1 = new TreeItem<>(new Person("Group 1"));
TreeItem<Person> group2 = new TreeItem<>(new Person("Group 2"));
TreeItem<Person> group3 = new TreeItem<>(new Person("Group 3"));
root.getChildren().addAll(group1, group2, group3);
TreeItem<Person> employee1 = new TreeItem<>(new Person("Employee 1"));
TreeItem<Person> employee2 = new TreeItem<>(new Person("Employee 2"));
group2.getChildren().addAll(employee1, employee2);
TreeTableColumn<Person, String> nameColumn = new TreeTableColumn<>(
"Name");
nameColumn.setPrefWidth(300);
nameColumn
.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>(
"name"));
view.getColumns().add(nameColumn);
// LISTENER
view.expandedItemCountProperty().addListener(
new ChangeListener<Number>() {
@Override
public void changed(
ObservableValue<? extends Number> observableValue,
Number oldCount, Number newCount) {
System.out.println("new expanded item count: "
+ newCount.intValue());
for (int i = 0; i < newCount.intValue(); i++) {
TreeItem<Person> item = view.getTreeItem(i);
Person person = item.getValue();
System.out.println("person found at index " + i
+ " is " + person.getName());
}
System.out
.println("------------------------------------------");
}
});
Scene scene = new Scene(view);
stage.setScene(scene);
stage.sizeToScene();
stage.show();
}
public class Person {
public Person(String name) {
nameProperty().set(name);
}
private StringProperty name = new SimpleStringProperty();
public StringProperty nameProperty() {
return name;
}
public String getName() {
return nameProperty().get();
}
}
public static void main(String[] args) {
Application.launch(args);
}
}
The following program demonstrates the issue. Please pay attention to the output in the console. The problem will manifest itself after expanding / collapsing "group2".
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.scene.control.cell.TreeItemPropertyValueFactory;
import javafx.stage.Stage;
public class TestExpandedItemCountBug extends Application {
@Override
public void start(Stage stage) throws Exception {
final TreeTableView<Person> view = new TreeTableView<>();
view.setPrefSize(300, 500);
TreeItem<Person> root = new TreeItem<>(new Person("Boss"));
view.setRoot(root);
TreeItem<Person> group1 = new TreeItem<>(new Person("Group 1"));
TreeItem<Person> group2 = new TreeItem<>(new Person("Group 2"));
TreeItem<Person> group3 = new TreeItem<>(new Person("Group 3"));
root.getChildren().addAll(group1, group2, group3);
TreeItem<Person> employee1 = new TreeItem<>(new Person("Employee 1"));
TreeItem<Person> employee2 = new TreeItem<>(new Person("Employee 2"));
group2.getChildren().addAll(employee1, employee2);
TreeTableColumn<Person, String> nameColumn = new TreeTableColumn<>(
"Name");
nameColumn.setPrefWidth(300);
nameColumn
.setCellValueFactory(new TreeItemPropertyValueFactory<Person, String>(
"name"));
view.getColumns().add(nameColumn);
// LISTENER
view.expandedItemCountProperty().addListener(
new ChangeListener<Number>() {
@Override
public void changed(
ObservableValue<? extends Number> observableValue,
Number oldCount, Number newCount) {
System.out.println("new expanded item count: "
+ newCount.intValue());
for (int i = 0; i < newCount.intValue(); i++) {
TreeItem<Person> item = view.getTreeItem(i);
Person person = item.getValue();
System.out.println("person found at index " + i
+ " is " + person.getName());
}
System.out
.println("------------------------------------------");
}
});
Scene scene = new Scene(view);
stage.setScene(scene);
stage.sizeToScene();
stage.show();
}
public class Person {
public Person(String name) {
nameProperty().set(name);
}
private StringProperty name = new SimpleStringProperty();
public StringProperty nameProperty() {
return name;
}
public String getName() {
return nameProperty().get();
}
}
public static void main(String[] args) {
Application.launch(args);
}
}