假设我将一个ChangeListener添加到TableView的itemsProperty中。何时会调用ChangeListener的更改方法?
我尝试添加TableView项目指向的空List。结果 - 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);
但是,我也尝试添加一个空List,然后让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本身的类型相匹配。”
我问这个是因为我可能会错过其他一些重要的情况。
答案 0 :(得分: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!
如果您的代码想要监听内容的更改,那就太讨厌了 - 每当项目值的标识发生变化时,它都需要重新连接ListChangeListener,但是不能使用changeListener,因为它基于相等性而触发。顺便说一句,甚至fx内部代码也出错了hot-fixed by a dirty hack
没有好的解决方案,只有一个couple of suboptimal options
我使用的代码段:
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;
}
答案 1 :(得分: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);