Sync between visual content and backing data is broken, if the edited value is not written back into the item. The example below simply uses read-only data (effect is the same if a custom handler rejects the edit)
To reproduce, run the example, edit a value, commit
- expected: cell shows old value
- actual: cell shows edited value
To verify the mismatch, click onto the button to see that the backing data is the old. Decrease window size until the edited row is not visible, then increasse again to see that the correct old value appears again.
The example:
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TablePosition;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
/**
* TableViewCell: representation may be incorrect after commitEdit
*
*/
public class TableViewEditNotWritable extends Application {
TablePosition<Dummy, String> editPosition;
private Object editValue;
@Override
public void start(Stage primaryStage) {
TableView<Dummy> table = new TableView<>(Dummy.dummies());
table.setEditable(true);
TableColumn<Dummy, String> first = new TableColumn<>("Text");
first.setCellFactory(TextFieldTableCell.forTableColumn());
first.setCellValueFactory(new PropertyValueFactory<>("dummy"));
first.setOnEditStart(t -> editPosition = t.getTablePosition());
first.addEventHandler(first.editCommitEvent(), t -> {
editValue = t.getNewValue();
System.out.println("doing nothing");
});
table.getColumns().addAll(first);
Button button = new Button("Check value");
button.setOnAction(e -> {
if (editPosition == null) return;
String value = editPosition.getTableColumn().getCellObservableValue(editPosition.getRow()).getValue();
System.out.println(
"value in edited cell must represent backing data: " + value + " not the edited " + editValue);
});
BorderPane root = new BorderPane(table);
root.setBottom(button);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
public static class Dummy {
private String dummy;
public Dummy(String dummy) {
this.dummy = dummy;
}
public String getDummy() {
return dummy;
}
public static ObservableList<Dummy> dummies() {
return FXCollections.observableArrayList(
new Dummy("1"), new Dummy("2"), new Dummy("3")
);
}
}
}
To reproduce, run the example, edit a value, commit
- expected: cell shows old value
- actual: cell shows edited value
To verify the mismatch, click onto the button to see that the backing data is the old. Decrease window size until the edited row is not visible, then increasse again to see that the correct old value appears again.
The example:
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TablePosition;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
/**
* TableViewCell: representation may be incorrect after commitEdit
*
*/
public class TableViewEditNotWritable extends Application {
TablePosition<Dummy, String> editPosition;
private Object editValue;
@Override
public void start(Stage primaryStage) {
TableView<Dummy> table = new TableView<>(Dummy.dummies());
table.setEditable(true);
TableColumn<Dummy, String> first = new TableColumn<>("Text");
first.setCellFactory(TextFieldTableCell.forTableColumn());
first.setCellValueFactory(new PropertyValueFactory<>("dummy"));
first.setOnEditStart(t -> editPosition = t.getTablePosition());
first.addEventHandler(first.editCommitEvent(), t -> {
editValue = t.getNewValue();
System.out.println("doing nothing");
});
table.getColumns().addAll(first);
Button button = new Button("Check value");
button.setOnAction(e -> {
if (editPosition == null) return;
String value = editPosition.getTableColumn().getCellObservableValue(editPosition.getRow()).getValue();
System.out.println(
"value in edited cell must represent backing data: " + value + " not the edited " + editValue);
});
BorderPane root = new BorderPane(table);
root.setBottom(button);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
public static class Dummy {
private String dummy;
public Dummy(String dummy) {
this.dummy = dummy;
}
public String getDummy() {
return dummy;
}
public static ObservableList<Dummy> dummies() {
return FXCollections.observableArrayList(
new Dummy("1"), new Dummy("2"), new Dummy("3")
);
}
}
}
- links to
-
Commit openjdk/jfx/ead19536
-
Review(master) openjdk/jfx/1197