2013-10-04 3 views
1

Предположим, что я добавлю ChangeListener в ItemProperty TableView. Когда будет вызван метод изменения ChangeListener?Странное поведение TableView.itemsProperty?

Я попытался добавить в пустой список, где указаны элементы TableView. Результат. Измененный метод ChangeListener не вызывался.

Однако, я также попытался добавить в пустой список, а затем указать пункты 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 к список многозначных свойств объекта и слушать второй
  • использовать адаптер, который сочетает в себе выше, по крайней мере, его от пути

Код фрагмента, который я использую:

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); 

это вы обновит TableView, поскольку таблица наблюдает ObservableList itemListX.

2-Else, если вы не больше:

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

Thanks Magcus, произошла ошибка. Это не tableView.add (новый Object()), это tableView.getItems(). Add (new Object()); Я редактировал свой вопрос. В любом случае, вы можете сказать, почему tableView.getItems(). Add (new Object()); не уведомил ChangeListener, связанный с itemsProperty tableView? –

+0

Можете ли вы добавить остальную часть кода? Специально набор изменений. Потому что в моих проектах он отлично работает ... – Magcus

+0

Хорошо, я попытаюсь отредактировать свой вопрос через некоторое время. –

Смежные вопросы