title: JavaFX table row update
body: <p>The scenario i am trying to achieve is,</p>
  
  <ol>
  <li>Whenever a particular <code>TableCell</code> in a <code>TableRow</code> gets updated , the row color will be changed to red and after 3 seconds the color should be automatically reverted to original. </li>
  </ol>
  
  <p>below is <strong>MCVE</strong>,</p>
  
  <p><strong>Main Class</strong></p>
  
  <pre><code>import java.util.concurrent.ExecutorService;
  import java.util.concurrent.Executors;
  import javafx.application.Application;
  import javafx.collections.FXCollections;
  import javafx.collections.ObservableList;
  import javafx.scene.Scene;
  import javafx.scene.control.TableColumn;
  import javafx.scene.control.TableView;
  import javafx.stage.Stage;
  
  public class TestProjectWin10 extends Application {
      private final ObservableList&lt;Element&gt; data = FXCollections.observableArrayList();
  
      public final Runnable changeValues = () -&gt; {
          int i = 0;
          while (i &lt;= 100000) {
              if (Thread.currentThread().isInterrupted()) {
                  break;
              }
              data.get(0).setOccurence(System.currentTimeMillis());
              data.get(0).count();
              i = i + 1;
          }
      };
  
      private final ExecutorService executor = Executors.newSingleThreadExecutor(runnable -&gt; {
          Thread t = new Thread(runnable);
          t.setDaemon(true);
          return t;
      });
  
      @Override
      public void start(Stage primaryStage) {
  
          TableView&lt;Element&gt; table = new TableView&lt;&gt;();
          table.getStylesheets().add(this.getClass().getResource("tableColor.css").toExternalForm());
          table.setEditable(true);
  
          TableColumn&lt;Element, String&gt; nameCol = new TableColumn&lt;&gt;("Name");
          nameCol.setPrefWidth(200);
          nameCol.setCellValueFactory(cell -&gt; cell.getValue().nameProperty());
          nameCol.setCellFactory((TableColumn&lt;Element, String&gt; param) -&gt; new ColorCounterTableCellRenderer(table));
          table.getColumns().add(nameCol);
  
          this.data.add(new Element());
          table.setItems(this.data);
  
          this.executor.submit(this.changeValues);
  
          Scene scene = new Scene(table, 600, 600);
          primaryStage.setScene(scene);
          primaryStage.show();
      }
  
      public static void main(String[] args) {
          launch(args);
      }
  }
  </code></pre>
  
  <p><strong>The Element Class:</strong></p>
  
  <pre><code>import java.util.concurrent.atomic.AtomicReference;
  
  import javafx.application.Platform;
  import javafx.beans.property.DoubleProperty;
  import javafx.beans.property.SimpleDoubleProperty;
  import javafx.beans.property.SimpleStringProperty;
  import javafx.beans.property.StringProperty;
  
  public class Element {
      int x = 0;
  
      private final StringProperty nameProperty = new SimpleStringProperty("");
  
      private final AtomicReference&lt;String&gt; name = new AtomicReference&lt;&gt;();
  
      private final DoubleProperty occurence = new SimpleDoubleProperty();
  
      public void count() {
          x = x + 1;
          if (name.getAndSet(Integer.toString(x)) == null) {
              Platform.runLater(() -&gt; nameProperty.set(name.getAndSet(null)));
          }
      }
  
      public void setOccurence(double value) {
          occurence.set(value);
      }
  
      public String getName() {
          return nameProperty().get();
      }
  
      public void setName(String name) {
          nameProperty().set(name);
      }
  
      public StringProperty nameProperty() {
          return nameProperty;
      }
  
      double getOccurrenceTime() {
          return occurence.get();
      }
  }
  </code></pre>
  
  <p><strong>CellFactory code:</strong></p>
  
  <pre><code>import java.util.Timer;
  import java.util.TimerTask;
  import javafx.application.Platform;
  import javafx.geometry.Pos;
  import javafx.scene.control.TableCell;
  import javafx.scene.control.TableRow;
  import javafx.scene.control.TableView;
  
  public class ColorCounterTableCellRenderer extends TableCell&lt;Element, String&gt; {
  
      private final static long MAX_MARKED_TIME = 3000;
      private final static long UPDATE_INTERVAL = 1000;
  
      private static Timer t = null;
      private final String highlightedStyle = "highlightedRow";
  
      private final TableView tv;
  
      public ColorCounterTableCellRenderer(TableView tv) {
          this.tv = tv;
          createTimer();
          setAlignment(Pos.CENTER_RIGHT);
      }
  
      private void createTimer() {
          if (t == null) {
              t = new Timer("Hightlight", true);
              t.schedule(new TimerTask() {
                  @Override
                  public void run() {
  
                      final long currentTime = System.currentTimeMillis();
  
                      TableRow tr = getTableRow();
                      if (tr.getItem() != null) {
  
                          if (currentTime - ((Element) tr.getItem()).getOccurrenceTime() &gt; MAX_MARKED_TIME) {
                              Platform.runLater(() -&gt; {
                                  tr.getStyleClass().remove(highlightedStyle);
                              });
                          }
                      }
                  }
              }, 0, UPDATE_INTERVAL);
          }
      }
  
      @Override
      protected void updateItem(String item, boolean empty) {
          if (empty || getTableRow() == null || getTableRow().getItem() == null) {
              setText(null);
              return;
          }
  
          long currentTime = System.currentTimeMillis();
  
          TableRow&lt;Element&gt; row = getTableRow();
          Element elementRow = row.getItem();
  
          double occurrenceTime = elementRow.getOccurrenceTime();
  
          if (currentTime - occurrenceTime &lt; MAX_MARKED_TIME) {
              if (!row.getStyleClass().contains(highlightedStyle)) {
                  row.getStyleClass().add(highlightedStyle);
              }
          }
  
          super.updateItem(item, empty);
          setText(item + "");
  
      }
  }
  </code></pre>
  
  <p>and the css file tableColor.css</p>
  
  <pre><code>.highlightedRow {
      -fx-background-color: rgba(255,0,0, 0.25);
      -fx-background-insets: 0, 1, 2;
      -fx-background: -fx-accent;
      -fx-text-fill: -fx-selection-bar-text;    
  }
  </code></pre>
  
  <p>What is the issue..?</p>
  
  <ol>
  <li><p>I check whether difference between the current time and update happened time is less than 3 seconds - row color to red (in <code>ColorCounterTableCellRenderer</code> - <code>updateItem</code> method)</p></li>
  <li><p>in a separate timer (<code>ColorCounterTableCellRenderer</code>) , i try check whether difference between current time and update happened time is more than 3 seconds - Removing red color.</p></li>
  </ol>
  
  <p>But in the timer (<code>createTimer</code> - method) code : the <code>tr.getItem()</code> is always <code>null</code> and hence not removing red color.</p>
  
  <p>Is this the correct way to achieve what i want? Why <code>tr.getItem()</code> returns <code>null</code>.</p>
  
  <p><strong>To test</strong> : I ran the code and waited for <code>executor</code> code to end and checked whether red color is removed after 3 seconds.</p>