-
Bug
-
Resolution: Fixed
-
P3
-
8u60
-
Fedora release 20 (Heisenbug)
java version "1.8.0_60-ea"
Java(TM) SE Runtime Environment (build 1.8.0_60-ea-b10)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b10, mixed mode)
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8129460 | 8u60 | Jonathan Giles | P3 | Resolved | Fixed |
While a lot of things seem to have been fixed in 8u60 I just noticed new weird things with regards to the selected Items of a table. If you run the following program and do nothing (i.e. not select anything at all) I would expect that selectionChanged ist never called (since the selection does not in fact change).
However the output is:
Added: [0Doe]
Reloading
Removed:[0Doe, 1Doe, 2Doe, 3Doe, 4Doe, 5Doe, 6Doe, 7Doe, 8Doe, 9Doe, 10Doe, 11Doe, 12Doe, 13Doe, 14Doe, 15Doe, 16Doe, 17Doe, 18Doe, 19Doe, 20Doe, 21Doe, 22Doe, 23Doe, 24Doe, 25Doe, 26Doe, 27Doe, 28Doe, 29Doe, 30Doe, 31Doe, 32Doe, 33Doe, 34Doe, 35Doe, 36Doe, 37Doe, 38Doe, 39Doe, 40Doe, 41Doe, 42Doe, 43Doe, 44Doe, 45Doe, 46Doe, 47Doe, 48Doe, 49Doe]
Added: [0Doe]
---- SNIP ---
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener.Change;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import javafx.util.Duration;
@SuppressWarnings("all")
public class TableViewSelectionBug extends Application {
ObservableList<Person> items = FXCollections.observableArrayList();
TableView<Person> table = new TableView<Person>();
Timeline reloadTimeline = new Timeline();
public TableViewSelectionBug() {
}
@Override
public void start(Stage primaryStage) throws Exception {
table.setItems(items);
TableColumn<Person, String> firstNameCol = new TableColumn<Person, String>("First Name");
firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
TableColumn<Person, String> lastNameCol = new TableColumn<Person, String>("Last Name");
lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
table.getColumns().setAll(firstNameCol, lastNameCol);
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
table.getSelectionModel().getSelectedItems().addListener(this::selectionChanged);
addPersons();
// reload data in 5 seconds
reloadTimeline.getKeyFrames().add(new KeyFrame(Duration.seconds(5), "Reload", (ActionEvent) -> {
reload();
}));
reloadTimeline.play();
Scene scene = new Scene(table, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
// simulate server call, usually this would take sort order property into account
private void addPersons() {
for (int i = 0; i < 50; i++) {
Person p = new Person();
int idx = items.size();
p.setFirstName(idx + " John");
p.setLastName(idx + "Doe");
items.add(p);
}
}
private void reload() {
System.out.println("Reloading");
table.getSelectionModel().clearSelection();
items.clear();
addPersons();
}
private void selectionChanged(Change<? extends Person> c) {
while (c.next()) {
if (c.wasRemoved()) {
System.out.println("Removed:" + c.getRemoved());
// ^^^ will throw Exception in thread "JavaFX Application Thread" java.util.NoSuchElementException, when a column header is clicked
}
if (c.wasAdded()) {
System.out.println("Added: " + c.getAddedSubList());
}
}
}
public static void main(String[] args) {
launch(args);
}
public class Person {
private StringProperty firstName;
public void setFirstName(String value) {
firstNameProperty().set(value);
}
public String getFirstName() {
return firstNameProperty().get();
}
public StringProperty firstNameProperty() {
if (firstName == null)
firstName = new SimpleStringProperty(this, "firstName");
return firstName;
}
private StringProperty lastName;
public void setLastName(String value) {
lastNameProperty().set(value);
}
public String getLastName() {
return lastNameProperty().get();
}
public StringProperty lastNameProperty() {
if (lastName == null)
lastName = new SimpleStringProperty(this, "lastName");
return lastName;
}
@Override
public String toString() {
return getLastName();
}
}
}
However the output is:
Added: [0Doe]
Reloading
Removed:[0Doe, 1Doe, 2Doe, 3Doe, 4Doe, 5Doe, 6Doe, 7Doe, 8Doe, 9Doe, 10Doe, 11Doe, 12Doe, 13Doe, 14Doe, 15Doe, 16Doe, 17Doe, 18Doe, 19Doe, 20Doe, 21Doe, 22Doe, 23Doe, 24Doe, 25Doe, 26Doe, 27Doe, 28Doe, 29Doe, 30Doe, 31Doe, 32Doe, 33Doe, 34Doe, 35Doe, 36Doe, 37Doe, 38Doe, 39Doe, 40Doe, 41Doe, 42Doe, 43Doe, 44Doe, 45Doe, 46Doe, 47Doe, 48Doe, 49Doe]
Added: [0Doe]
---- SNIP ---
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener.Change;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import javafx.util.Duration;
@SuppressWarnings("all")
public class TableViewSelectionBug extends Application {
ObservableList<Person> items = FXCollections.observableArrayList();
TableView<Person> table = new TableView<Person>();
Timeline reloadTimeline = new Timeline();
public TableViewSelectionBug() {
}
@Override
public void start(Stage primaryStage) throws Exception {
table.setItems(items);
TableColumn<Person, String> firstNameCol = new TableColumn<Person, String>("First Name");
firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
TableColumn<Person, String> lastNameCol = new TableColumn<Person, String>("Last Name");
lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
table.getColumns().setAll(firstNameCol, lastNameCol);
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
table.getSelectionModel().getSelectedItems().addListener(this::selectionChanged);
addPersons();
// reload data in 5 seconds
reloadTimeline.getKeyFrames().add(new KeyFrame(Duration.seconds(5), "Reload", (ActionEvent) -> {
reload();
}));
reloadTimeline.play();
Scene scene = new Scene(table, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
// simulate server call, usually this would take sort order property into account
private void addPersons() {
for (int i = 0; i < 50; i++) {
Person p = new Person();
int idx = items.size();
p.setFirstName(idx + " John");
p.setLastName(idx + "Doe");
items.add(p);
}
}
private void reload() {
System.out.println("Reloading");
table.getSelectionModel().clearSelection();
items.clear();
addPersons();
}
private void selectionChanged(Change<? extends Person> c) {
while (c.next()) {
if (c.wasRemoved()) {
System.out.println("Removed:" + c.getRemoved());
// ^^^ will throw Exception in thread "JavaFX Application Thread" java.util.NoSuchElementException, when a column header is clicked
}
if (c.wasAdded()) {
System.out.println("Added: " + c.getAddedSubList());
}
}
}
public static void main(String[] args) {
launch(args);
}
public class Person {
private StringProperty firstName;
public void setFirstName(String value) {
firstNameProperty().set(value);
}
public String getFirstName() {
return firstNameProperty().get();
}
public StringProperty firstNameProperty() {
if (firstName == null)
firstName = new SimpleStringProperty(this, "firstName");
return firstName;
}
private StringProperty lastName;
public void setLastName(String value) {
lastNameProperty().set(value);
}
public String getLastName() {
return lastNameProperty().get();
}
public StringProperty lastNameProperty() {
if (lastName == null)
lastName = new SimpleStringProperty(this, "lastName");
return lastName;
}
@Override
public String toString() {
return getLastName();
}
}
}
- backported by
-
JDK-8129460 TableView selected items listener reports wrong changes
-
- Resolved
-