title: Updating ObservableList after editing cell in TableView
body: <p>I'm trying to create editable cells using Oracle poor tutorial. I figured out that their <code>EditCell</code> class only updates when I click on the same row I currently edit or outside any row. In case when I click on another row, edit is cancelled. Here is the link to this tutorial and on the end of it you can find <code>EditCell</code> class, but it's not the point of this question: </p>
  
  <p><a href="https://docs.oracle.com/javase/8/javafx/user-interface-tutorial/table-view.htm" rel="nofollow noreferrer">https://docs.oracle.com/javase/8/javafx/user-interface-tutorial/table-view.htm</a></p>
  
  <p>This class creates <code>TextField</code> for edit purposes. Clicking on another row launches <code>cancel()</code> method. And there is this code line:</p>
  
  <pre><code>setText((String( getItem());
  </code></pre>
  
  <p>that blocks edit. I replaced it with:</p>
  
  <pre><code>setText((String) textField.getText());
  </code></pre>
  
  <p>and edit works now. But after editing this cell again old value is loaded to <code>TextField</code>. I guess that <code>ObservableList</code> is not updated after first edit.</p>
  
  <p>Here is FXML code:</p>
  
  <pre><code>&lt;GridPane fx:controller="sample.Controller"
        xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10"&gt;
  
      &lt;TableView GridPane.columnIndex="0" GridPane.rowIndex="1" items="${controller.data}" editable="true"&gt;
          &lt;columns&gt;
              &lt;TableColumn fx:id="colName" text="name"&gt;
                  &lt;cellValueFactory&gt;
                      &lt;PropertyValueFactory property="Name"/&gt;
                  &lt;/cellValueFactory&gt;
              &lt;/TableColumn&gt;
  
              &lt;TableColumn fx:id="colSurname" text="surname"&gt;
                  &lt;cellValueFactory&gt;
                      &lt;PropertyValueFactory property="Surname"/&gt;
                  &lt;/cellValueFactory&gt;
              &lt;/TableColumn&gt;
          &lt;/columns&gt;
      &lt;/TableView&gt;
  &lt;/GridPane&gt;
  </code></pre>
  
  <p>In controller I declare <code>ObservableList</code>:</p>
  
  <pre><code>public class Controller {
  
      @FXML
      private TableColumn&lt;Person, String&gt; colName;
      @FXML
      private TableColumn&lt;Person, String&gt; colSurname;
  
      @FXML
      private ObservableList&lt;Person&gt; data;
  
      public Controller(){
          data = FXCollections.observableArrayList(
                  new Person("John", "S."),
                  new Person("Jane", "S.")
          );
      }
  
      public TableColumn&lt;Person, String&gt; getColName() {
          return colName;
      }
  
      public void setColName(TableColumn&lt;Person, String&gt; colName) {
          this.colName = colName;
      }
  
      public TableColumn&lt;Person, String&gt; getColSurname() {
          return colSurname;
      }
  
      public void setColSurname(TableColumn&lt;Person, String&gt; colSurname) {
          this.colSurname = colSurname;
      }
  
      public ObservableList&lt;Person&gt; getData() {
          return data;
      }
  
      public void setData(ObservableList&lt;Person&gt; data) {
          this.data = data;
      }
  }
  </code></pre>
  
  <p>Person.java code:</p>
  
  <pre><code>public class Person {
  
      private final SimpleStringProperty name;
      private final SimpleStringProperty surname;
  
      public Person(String name, String surname){
          this.name = new SimpleStringProperty(name);
          this.surname = new SimpleStringProperty(surname);
      }
  
      public String getName() {
          return name.get();
      }
  
      public SimpleStringProperty nameProperty() {
          return name;
      }
  
      public void setName(String name) {
          this.name.set(name);
      }
  
      public String getSurname() {
          return surname.get();
      }
  
      public SimpleStringProperty surnameProperty() {
          return surname;
      }
  
      public void setSurname(String surname) {
          this.surname.set(surname);
      }
  }
  </code></pre>
  
  <p>In <code>Main</code> I declare controller and editable column:</p>
  
  <pre><code>public class Main extends Application {
  
      @Override
      public void start(Stage primaryStage) throws Exception {
          FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
  
          Parent root = (Parent) loader.load();
          primaryStage.setScene(new Scene(root, 300, 275));
  
          Controller controller = loader.getController();
          TableColumn&lt;Person, String&gt; colName = controller.getColName();
  
          Callback&lt;TableColumn&lt;Person, String&gt;, TableCell&lt;Person, String&gt;&gt; cellFactory =
              (TableColumn&lt;Person, String&gt; p) -&gt; new sample.EditCell();
  
          colName.setCellFactory(cellFactory);
          colName.setOnEditCommit(
                  (TableColumn.CellEditEvent&lt;Person, String&gt; t) -&gt; {
                      ((Person) t.getTableView().getItems().get(
                              t.getTablePosition().getRow())
                      ).setName(t.getNewValue());
                  });
  
  
          primaryStage.show();
      }
  
      public static void main(String[] args) {
         launch(args);
      }
  }
  </code></pre>
  
  <p>Do I need bind cell with <code>ObservableList</code>? Or refresh it? How to update <code>data</code> to have TextField always filled with actual value?</p>
  
  <p>Here is whole <code>EditCell</code> class:</p>
  
  <pre><code>class EditCell extends TableCell&lt;Person, String&gt; {
  
      private TextField textField;
  
      public EditCell() {
      }
  
      @Override
      public void startEdit() {
          if (!isEmpty()) {
              super.startEdit();
              createTextField();
              setText(null);
              setGraphic(textField);
              textField.selectAll();
          }
      }
  
      @Override
      public void cancelEdit() {
          super.cancelEdit();
  
          setText((String) getItem());
  
          //setText((String) textField.getText());
          //This line updates cell, but textField keeps old value after next edit.
  
          setGraphic(null);
      }
  
      @Override
      public void updateItem(String item, boolean empty) {
          super.updateItem(item, empty);
  
          if (empty) {
              setText(null);
              setGraphic(null);
          } else {
              if (isEditing()) {
                  if (textField != null) {
                      textField.setText(getString());
                  }
  
                  setText(null);
                  setGraphic(textField);
              } else {
                  setText(getString());
                  setGraphic(null);
              }
          }
      }
  
      private void createTextField() {
          textField = new TextField(getString());
          textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
          textField.focusedProperty().addListener(
                  (ObservableValue&lt;? extends Boolean&gt; arg0,
                   Boolean arg1, Boolean arg2) -&gt; {
                      if (!arg2) {
                          commitEdit(textField.getText());
                      }
                  });
      }
  
      private String getString() {
          return getItem() == null ? "" : getItem().toString();
      }
  }
  </code></pre>