从ObjectProperty更新事件(就像在ObservableList中一样) [英] Update events from ObjectProperty (just like in ObservableList)
问题描述
我可以使用提取器( Callback< E,Observable []>提取器
)来制作 ListProperty
如果其中一个元素更改了其中一个属性(更新事件),则触发更改事件。
I can use an extractor (Callback<E, Observable[]> extractor
) to make a ListProperty
fire change events if one of its elements changed one of its properties (update event).
ObjectProperty< >
?我有一个 SimpleObjectProperty
我希望在它的值(另一个bean类型)的属性发生变化时触发事件(更新更改事件)。
Is there an equivalent for ObjectProperty<>
? I have an SimpleObjectProperty
which I want to fire events when properties of it's value (another bean type) change (update change events).
示例代码:
public class TestBean {
public static <T extends TestBean> Callback<T, Observable[]> extractor() {
return (final T o) -> new Observable[] { o.testPropertyProperty() };
}
private final StringProperty testProperty = new SimpleStringProperty();
public final StringProperty testPropertyProperty() {
return this.testProperty;
}
public final String getTestProperty() {
return this.testPropertyProperty().get();
}
public final void setTestProperty(final String testProperty) {
this.testPropertyProperty().set(testProperty);
}
}
public class SomeType {
/**
* How can I listen for changes of TestBean#testProperty?
*/
private final ObjectProperty<TestBean> property = new SimpleObjectProperty<>();
}
如果值<$,我想收到更改事件c $ c> SomeType#property 更改,但是,如果 SomeType#property#testProperty
更改。
I want to receive change events if the value of SomeType#property
changes, but also, if SomeType#property#testProperty
changes.
我不能只听 SomeType#property#testProperty
,因为当 SomeType#property $ c $时我不会收到通知c>被更改了(我会在错误的对象上听取更改)。
I cannot just listen for SomeType#property#testProperty
, since I would not be notified when SomeType#property
was changed (I would then listen on the wrong object for changes).
推荐答案
上周我遇到了同样的问题,经过多次尝试,我找到了一个似乎按预期工作的解决方案:
I had the same problem last week, and after many tries, I found a solution that seems to work as expected:
- 我创建了一个名为
的新类ObjectXProperty< E>
,具有ObjectProperty< E>
; - 的相同界面构造函数可以接受
Callback< E,Observable []>
,我们的提取器函数; - 在
ObjectXProperty
,我使用SimpleObjectProperty
删除所有方法; -
神奇的技巧在于
集合(E值)
方法:我创建了一个ObjectBinding
只是简单地发回值,但是它使用提取器函数来决定它何时变为无效!
- I created a new class called
ObjectXProperty<E>
, that has the same interface of anObjectProperty<E>
; - It has constructors that can accept a
Callback<E,Observable[]>
, our extractor function; - Inside the
ObjectXProperty
, I use aSimpleObjectProperty
that deleguates all methods; The magic trick lies in the
set(E value)
methods : I create anObjectBinding
that simply send back the value, but it uses the extractor function to decide when it's become invalidated!
如果先前在<$ c $上使用 bind
方法,则不会应用此技巧c> ObjectXProperty ,让真正的绑定完成他的工作;如果调用 unbind
方法,它将再次起作用;
This trick will not be applied if the bind
method was used previously on the ObjectXProperty
, to let the "real" binding do his job; it will work again if the unbind
method is called;
这是我的新班级 ObjectXProperty< E>
:
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.util.Callback;
/**
*
* @author Claude Bouchard - 2017
*/
public class ObjectXProperty<E> extends ObjectProperty<E> {
SimpleObjectProperty<E> p;
Callback<E, Observable[]> extractor;
boolean externalBound = false;
public ObjectXProperty(Callback<E, Observable[]> extractor) {
this.extractor = extractor;
}
public ObjectXProperty(E init, Callback<E, Observable[]> extractor) {
p = new SimpleObjectProperty();
this.extractor = extractor;
set(init);
}
public ObjectXProperty(Object bean, String name, Callback<E, Observable[]> extractor) {
p = new SimpleObjectProperty(bean, name);
this.extractor = extractor;
}
public ObjectXProperty(Object bean, String name, E init, Callback<E, Observable[]> extractor) {
p = new SimpleObjectProperty(bean, name);
this.extractor = extractor;
set(init);
}
@Override
public void set(E value) {
if (!externalBound) {
if (value != null) {
p.bind(Bindings.createObjectBinding(() -> {
return value;
}, extractor.call(value)));
} else {
p.bind(Bindings.createObjectBinding(() -> {
return value;
}, new Observable[]{}));
}
} else {
p.set(value); //As expected, it will throw a java.lang.RuntimeException
}
}
@Override
public E get() {
return p.get();
}
@Override
public void addListener(ChangeListener<? super E> listener) {
p.addListener(listener);
}
@Override
public void removeListener(ChangeListener<? super E> listener) {
p.removeListener(listener);
}
@Override
public void addListener(InvalidationListener listener) {
p.addListener(listener);
}
@Override
public void removeListener(InvalidationListener listener) {
p.removeListener(listener);
}
@Override
public Object getBean() {
return p.getBean();
}
@Override
public String getName() {
return p.getName();
}
@Override
public void bind(ObservableValue<? extends E> observable) {
p.bind(observable);
externalBound = true;
}
@Override
public void unbind() {
p.unbind();
externalBound = false;
set(get()); //to reactivate the extractor on the last value
}
@Override
public boolean isBound() {
return externalBound;
}
}
这篇关于从ObjectProperty更新事件(就像在ObservableList中一样)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!