2013-10-04 29 views
1

假設我將一個ChangeListener添加到TableView的itemsProperty中。 ChangeListener的更改方法何時會被調用?Strange TableView.itemsProperty行爲?

我試着添加到ListView的項目指向的空列表。結果 - ChangeListener的更改方法沒有被調用。

tableView.itemsProperty().addListener(new ChangeListener() { 
    @Override 
    public void changed(ObservableValue ov, Object t, Object t1) { 
     System.out.println("Changed!"); 
    } 
}); 

final ObservableList data = FXCollections.observableArrayList(new ArrayList()); 
data.clear(); 
//data.add(new Object()); don't call this yet 
tableView.setItems(data); 
data.clear(); 
data.add(new Object()); 
tableView.setItems(data); 

但是,我也嘗試添加到一個空列表,然後讓TableView的項目指向它。結果 - ChangeListener更改後的方法被調用。

tableView.itemsProperty().addListener(new ChangeListener() { 
    @Override 
    public void changed(ObservableValue ov, Object t, Object t1) { 
     System.out.println("Changed!"); 
    } 
}); 

final ObservableList data = FXCollections.observableArrayList(new ArrayList()); 
data.clear(); 
data.add(new Object()); 
tableView.setItems(data); 
data.clear(); 
data.add(new Object()); 
tableView.setItems(data); 

我看着它在http://docs.oracle.com/javafx/2/api/javafx/scene/control/TableView.html#itemsProperty(),但它只是說「爲TableView中的底層數據模型。需要注意的是它有一個泛型類型,必須在自身的TableView的類型相匹配。」

我在問這個,因爲我可能錯過了其他一些重要的情況。

回答

3

一個不完全記錄的事實(又名:實施細節)是OBJECTPROPERTY只有

!oldValue.equals(newValue); // modulo null checking 

這是至關重要的一個列表火災值得注意的對象屬性,因爲如果它們的所有元素都相等,則列表被指定爲相等。特別是,所有的空列表是彼此相等,從而由另一空表替換一個空列表作爲你的第一個片段,不會使房地產火了:

// items empty initially 
TableView table = new TableView() 
table.itemsProperty().addListener(....) 
ObservableList empty = FXCollections.observableArrayList(); 
// replace initial empty list by new empty list 
table.setItems(empty); 
// no change event was fired! 

那是,如果你的代碼想聽變化討厭的內容 - 當項目值的標識發生變化時,它需要重新連接ListChangeListeners,但不能使用changeListener,因爲這會引發基於相等性的操作。順便說一句,即使是FX-內部代碼得到了錯誤,hot-fixed by a dirty hack

而且沒有很好的解決方案,您只需一個couple of suboptimal options

  • 使用InvalidationListener,而不是一個ChangeListener
  • 綁定(單向!)一個的ListProperty到列表值對象的屬性,並聽取後者
  • 使用結合以上至少擁有它註銷的方式
適配器210

我使用的代碼片段:

public static <T> ListProperty<T> listProperty(final Property<ObservableList<T>> property) { 
    Objects.requireNonNull(property, "property must not be null"); 
    ListProperty<T> adapter = new ListPropertyBase<T>() { 
     // PENDING JW: need weakListener? 
     private InvalidationListener hack15793; 
     { 
      Bindings.bindBidirectional(this, property); 
      hack15793 = o -> { 
       ObservableList<T> newItems =property.getValue(); 
       ObservableList<T> oldItems = get(); 
       // force rewiring to new list if equals 
       boolean changedEquals = (newItems != null) && (oldItems != null) 
         && newItems.equals(oldItems); 
       if (changedEquals) { 
        set(newItems); 
       } 
      }; 
      property.addListener(hack15793); 
     } 

     @Override 
     public Object getBean() { 
      return null; // virtual property, no bean 
     } 

     @Override 
     public String getName() { 
      return property.getName(); 
     } 

     @Override 
     protected void finalize() throws Throwable { 
      try { 
       Bindings.unbindBidirectional(property, this); 
       property.removeListener(hack15793); 
      } finally { 
       super.finalize(); 
      } 
     } 

    }; 
    return adapter; 
} 
0

的TableView不具備實施的方法添加view documentation

我的形式給出如下:

要初始化的TableView itemList中:

tableX.setItems(itemListX); 

你也可以通過使用初始化TableView的默認列表:

tableX.getItems.addAll(itemListX); 

在這種情況下,它將複製列表。

而且形式給出動態地添加項目:

1,如果你仍然有itemListX參考:

itemListX.add(item); 

因爲表觀察ObservableList itemListX這一點,你將更新的TableView。

2 - 否則,如果你沒有任何更多:

tableX.getItems().add(item); 
+0

謝謝馬格斯,有一個錯誤。它不是tableView.add(new Object()),它是tableView.getItems()。add(new Object());我編輯了我的問題。無論如何,你能告訴爲什麼tableView.getItems()。add(new Object());沒有通知附加到tableView的itemsProperty的ChangeListener? –

+0

你可以添加其餘的代碼嗎?特別是changelistener集。因爲在我的項目中,它完美地工作... – Magcus

+0

好吧,我會嘗試在一段時間內編輯我的問題。 –