Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8150525

TableView: data corruption when editing newly added item

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: P3
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 9
    • Component/s: javafx
    • Labels:
    • Environment:

      9-ea-104

      Description

      Happen if we call table.edit(row,... ) on a newly added item off the visible range. Looks like internals get confused.

      To reproduce, run the example below

       * - click addAndEdit to insert cell off the visual range and start edit
       * - click scrollBar to scroll to inserted cell
       * - click addAndEdit again
       * - expected: cell with "initial 51" is edited
       * - actual: cell with "initial 50" is edited
       * - type x at beginning of editor text field, commit by enter
       * - note two cells with "xinitial 50"
       * - scroll back and forth to get rid of the visual artefact (only one is really changed)
       * - note that "initial 51" is changed to "xinitial 50" - corrupted data!


      The example:

      public class TablePCoreAddAndEdit extends Application {

          private Parent getContent() {
              TableView<Dummy> table = new TableView<>(createData(50));
              table.setEditable(true);
              
              TableColumn<Dummy, String> column = new TableColumn<>("Value");
              column.setCellValueFactory(c -> c.getValue().valueProperty());
              column.setCellFactory(TextFieldTableCell.forTableColumn());
              column.setMinWidth(200);
              table.getColumns().addAll(column);
              
              // insert and start editing at an invisible row
              // in my environment, I see about 12 rows
              int insertIndex = 20;
              Button addAndEdit = new Button("AddAndEdit");
              addAndEdit.setOnAction(e -> {
                  Dummy dummy = new Dummy();
                  table.getItems().add(insertIndex, dummy);
                  table.edit(insertIndex, column);
                  LOG.info("insertIndex" + insertIndex + "isAtIndex " + table.getItems().indexOf(dummy) + dummy);
              });
              
              Button logEditing = new Button("LogEditing");
              logEditing.setOnAction(e-> {
                  TablePosition<?, ?> editingCell = table.getEditingCell();
                  LOG.info((editingCell != null
                          ? "editing row: " + editingCell.getRow() + table.getItems().get(editingCell.getRow()): "no editing cell")
                          + "value at insertIndex: " + table.getItems().get(insertIndex)
                          );
              });
              HBox buttons = new HBox(10, addAndEdit, logEditing);
              BorderPane content = new BorderPane(table);
              content.setBottom(buttons);
              return content;
          }

          private ObservableList<Dummy> createData(int size) {
              return FXCollections.observableArrayList(
                      Stream.generate(Dummy::new)
                      .limit(size)
                      .collect(Collectors.toList()));
          }
          
          private static class Dummy {
              private static int count;
              StringProperty value = new SimpleStringProperty(this, "value", "initial " + count++);
              public StringProperty valueProperty() {return value;}
              public String getValue() {return valueProperty().get(); }
              public void setValue(String text) {valueProperty().set(text); }
              public String toString() {return "[dummy: " + getValue() + "]";}
          }
          @Override
          public void start(Stage primaryStage) throws Exception {
              primaryStage.setScene(new Scene(getContent()));
              //primaryStage.setTitle(FXUtils.version());
              primaryStage.show();
          }
          
          public static void main(String[] args) {
              launch(args);
          }
          
          @SuppressWarnings("unused")
          private static final Logger LOG = Logger
                  .getLogger(TablePCoreAddAndEdit.class.getName());
      }

        Attachments

          Activity

            People

            • Assignee:
              jgiles Jonathan Giles
              Reporter:
              fastegal Jeanette Winzenburg
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: