title: Javafx: Detect ALL changes made to tableView including addition/deletion of table rows and cell edits on any table rows
body: <p>Given that I have a <code>tableView</code>, how can I track all the changes, i.e. a new row is added / deleted, <strong>one of the table cells has its value changed</strong>, and fire off the same event when any of these changes are detected ?</p>
  
  <p>At the moment, I have the following code below, which only manages to detect change if I add in a row. It is not able to detect changes when I <strong>edit a table cell of any row</strong> and when I delete a row. </p>
  
  <pre><code>    ObservableList&lt;Trade&gt; observableListOfTrades =FXCollections.observableArrayList();
  
  
      observableListOfTrades.add(newTrade);  
  fxTransactionLog.getItems().add(observableListOfTrades.get(observableListOfTrades.size()-1));
  
  
          observableListOfTrades.addListener(new ListChangeListener() {
              @Override
              public void onChanged(ListChangeListener.Change change) {
                  System.out.println("Detected a change! ");
              }
          });
  </code></pre>
  
  <p>As requested, I am posting my <code>Trade</code> Class</p>
  
  <pre><code>public class Trade{
  
  // properties
  private ObjectProperty&lt;LocalDate&gt; transactionDate;
  private StringProperty itemName;
  private StringProperty buySell;
  private DoubleProperty volume;
  private DoubleProperty price;
  private DoubleBinding transactionFee;
  
  
  public Trade(BuySell buySell, LocalDate transactionDate, double volume, double price){
      this.buySell = new SimpleStringProperty(buySell.toString());
      this.itemName = new SimpleStringProperty("testing");
      this.transactionDate = new SimpleObjectProperty&lt;LocalDate&gt;(transactionDate);
      this.volume = new SimpleDoubleProperty(volume);
      this.price = new SimpleDoubleProperty(price);
  }
  
  // getters
  public String getBuySell(){
      return this.buySell.get();
  }
  
  // return Property Object
  public StringProperty buySellProperty(){
      return this.buySell;
  }
  
  // setters
  public void setBuySell(String buySell){
      this.buySell.set(buySell);
  }
  
  public LocalDate getTransactionDate(){
      return this.transactionDate.getValue();
  }
  
  public ObjectProperty&lt;LocalDate&gt; transactionDateProperty(){
      return this.transactionDate;
  }
  
  public void setTransactionDate(LocalDate transactionDate){
      this.transactionDate.set(transactionDate);
  }
  
  
  public double getVolume(){
      return this.volume.get();
  }
  
  public DoubleProperty volumeProperty(){
      return this.volume;
  }
  
  public void setVolume(double volume){
      this.volume.set(volume);
  }
  
  
  public double getPrice(){
      return this.price.get();
  }   
  
  public DoubleProperty priceProperty(){
      return this.price;
  }
  
  public void setPrice(double price){
      this.price.set(price);
  }
  
  public String getItemName(){
      return this.itemName.getValue();
  }
  
  
  public double getTransactionFee(){
          this.transactionFee = this.price.multiply(this.volume).multiply(0.15);
          return this.transactionFee.getValue();
  }
  
  public DoubleBinding transactionFeeProperty(){
      return this.transactionFee;
  }
  
  
  
  public String toString(){
      return "Buy: " + getBuySell() + ", Transasction date: " + getTransactionDate() + ", Volume: " + getVolume() + ", Price: " + getPrice() + ", Transaction fee: " + getTransactionFee() ;
  }
  }
  </code></pre>