如果其中一个元素更改了其中一个属性(更新事件),我可以使用提取器(Callback<E, Observable[]> extractor
)发出ListProperty
个火灾更改事件。
Update Change Event in ObservableList
是否有ObjectProperty<>
的等价物?我有一个SimpleObjectProperty
,当它的值(另一个bean类型)的属性发生变化时,我想触发事件(更新变更事件)。
示例代码:
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<>();
}
如果SomeType#property
的值发生变化,我希望收到更改事件,如果SomeType#property#testProperty
发生变化,我也希望收到更改事件。
我不能只听SomeType#property#testProperty
,因为当SomeType#property
被更改时我不会收到通知(然后我会听错对象的更改)。
答案 0 :(得分:1)
如果
SomeType#property
的值发生变化,我希望收到更改事件,如果SomeType#property#testProperty
发生变化,我也希望收到更改事件。我不能只听
SomeType#property#testProperty
,因为当SomeType#property
被更改时我不会收到通知(然后我会听错对象的更改)。
这是对JavaFX当前迭代的各种限制。内置方式不可靠,您最好使用第三方库。有关详细信息,请参阅此answer。
对于您的情况,ReactFX可以以类似的方式使用:
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import org.reactfx.value.Val;
import org.reactfx.value.Var;
class TestBean {
private final StringProperty testProperty = new SimpleStringProperty();
public final StringProperty testPropertyProperty() { return testProperty; }
public final String getTestProperty() { return testProperty.get(); }
public final void setTestProperty(String newTestProperty) { testProperty.set(newTestProperty); }
}
public class SomeType {
private final ObjectProperty<TestBean> property = new SimpleObjectProperty<>();
public final ObjectProperty<TestBean> propertyProperty() { return property; }
public final TestBean getProperty() { return property.get(); }
public final void setProperty(TestBean newProperty) { property.set(newProperty); }
public static void main(String[] args) {
SomeType someType = new SomeType();
Var<String> chainedTestProperty = Val.selectVar(someType.propertyProperty(), TestBean::testPropertyProperty);
chainedTestProperty.addListener((obs, oldVal, newVal) -> System.out.println(obs + " " + oldVal + "->" + newVal));
//Tests
someType.setProperty(new TestBean());
someType.getProperty().setTestProperty("s1");
TestBean bean2 = new TestBean();
bean2.setTestProperty("s2");
someType.setProperty(bean2);
someType.setProperty(new TestBean());
}
}
输出:
org.reactfx.value.FlatMappedVar@7aec35a null->s1
org.reactfx.value.FlatMappedVar@7aec35a s1->s2
org.reactfx.value.FlatMappedVar@7aec35a s2->null
关键线
Var<String> chainedTestProperty = Val.selectVar(someType.propertyProperty(), TestBean::testPropertyProperty);
是一种听众链接。第一个参数是某种类型OvservableValue
的属性(Type
)。第二个参数是Type2
中某些其他类型Type
的&#34; sub&#34; -property,它是从Type
到该属性的函数。
现在每当有任何&#34;链接&#34;在链变化中,您会收到通知。你可以通过这种方式连续链接ovservable来继续监听sub-sub -...属性的变化。
答案 1 :(得分:1)
上周我遇到了同样的问题,经过多次尝试,我找到了一个似乎按预期工作的解决方案:
ObjectXProperty<E>
的新类,它具有ObjectProperty<E>
的相同接口; Callback<E,Observable[]>
,我们的提取函数; ObjectXProperty
内,我使用SimpleObjectProperty
删除所有方法; 神奇的诀窍在于set(E value)
方法:我创建一个ObjectBinding
只需发回值,但它使用提取函数来决定何时它变得无效!
如果先前在bind
上使用ObjectXProperty
方法,则不会应用此技巧,让“真正的”绑定完成他的工作;如果调用unbind
方法,它将再次起作用;
这是我的新课程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;
}
}
答案 2 :(得分:0)
我想出了以下内容:
ExpressionHelper$SingleChange
不幸的是,由于@Override
protected void fireValueChangedEvent() {
final T oldValue = currentValue;
currentValue = observable.getValue();
final boolean changed = (currentValue == null)? (oldValue != null) : !currentValue.equals(oldValue);
if (changed) {
try {
listener.changed(observable, oldValue, currentValue);
} catch (Exception e) {
Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
}
}
}
:
fireValueChangedEvent()
这会检查是否相等,只有在不相等的情况下才会通知所有侦听器。当我触发angular.element(appElement).scope()
时,值已经改变,并且新旧值相等,因此没有通知听众。
答案 3 :(得分:-1)
我认为你需要为你的对象添加一个监听器。这可以简单地完成。首先,你应该用构造函数和getter这样编写你的类:
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
public class SomeType {
public ObjectProperty<TestProperty> property;
public SomeType(TestProperty testProperty) {
this.property = new SimpleObjectProperty<>(testProperty);
}
public TestProperty getProperty() {
return property.get();
}
public ObjectProperty<TestProperty> propertyProperty() {
return property;
}
}
然后,只要您拥有SomeType
的实例,就可以链接属性,这样就可以获得property
属性的testProperty()
,然后只需添加一个监听器。
someType.getProperty().testProperty().addListener((observable, oldValue, newValue) -> {
// Do whatever you want if the its value changed.
// You can also use its old or new value.
});