如何从ObservableValue继承?

时间:2018-06-11 16:23:04

标签: java javafx properties

我有一个包含各种属性的类:

public class Foo extends ??? {
    public SimpleBooleanProperty prop1 = new SimpleBooleanProperty();
    public SimpleStringProperty prop2 = new SimpleStringProperty();

    // ** more properties ** //
}

在大多数情况下,所有属性都会发生变化,对于某些侦听器,当任何属性发生变化时,只能调用一个回调,然后获取所有属性的值(即使并非所有属性都已更改)也会更容易。我应该建立什么课程?

我想在

行注册一个听众
Foo foo = new Foo();
foo.addListener( new ChangeListener< >() {
      void onChange(Foo newValue,Foo oldValue) {
           System.out.println(String.valueOf(newValue.prop1.get());
           System.out.println(String.valueOf(newValue.prop2.get());
      });

打印到控制台只是一个例子,关键是监听器只需要知道某些内容发生了变化,并且可以调用getter。我有点迷失在哪里开始。有Observable接口和大量不同的基类(例如ObservableValueBase<T>SimpleObjectProperty<T>)。我应该从/ extend继承哪一个?

2 个答案:

答案 0 :(得分:0)

实现ObservableValue<Foo>作为您的监听器建议意味着您的对象正在包装Foo对象,显然不是这样。

对于ObservableValue,会有要扩展的类。对于Observable,不存在此类,您应该自己实现该接口。这可以通过向/从所有Observable属性添加/删除侦听器来完成,但为了提高效率,我建议每个属性使用一个侦听器来实现:

public abstract class ObservableBase implements Observable {

    private final List<InvalidationListener> listeners = new ArrayList<>();

    protected ObservableBase(Observable... dependencies) {
        InvalidationListener listener = o -> {
            for (InvalidationListener l : listeners) {
                try {
                    l.invalidated(o);
                } catch (RuntimeException ex) {
                    ex.printStackTrace();
                }
            }
        };
        for (Observable o : dependencies) {
            o.addListener(listener);
        }
    }

    @Override
    public final void addListener(InvalidationListener listener) {
         Objects.requireNonNull(listener);
         listeners.add(listener);
    }

    @Override
    public final void removeListener(InvalidationListener listener) {
         listeners.remove(listener);
    }
}
public class Foo extends ObservableBase {
    public final BooleanProperty prop1;
    public final StringProperty prop2;

    // ** more properties ** //

    private Foo(BooleanProperty prop1, StringProperty prop2) {
        super(prop1, prop2);
        this.prop1 = prop1;
        this.prop2 = prop2;
    }

    public Foo() {
        this(new SimpleBooleanProperty(this, "prop1"), new SimpleStringProperty(this, "prop2"));
    }
}
Foo foo = new Foo();
InvalidationListener l = o -> {
    ReadOnlyProperty p = (ReadOnlyProperty) o;
    System.out.println("changed property: " + p.getName());

    Foo bean = (Foo) p.getBean();

    System.out.println(bean.prop1.get());
    System.out.println(bean.prop2.get());
};
foo.addListener(l);

答案 1 :(得分:0)

不完全确定我是否正确解释了您的需求。这可能就是你所需要的:

public class Foo extends ??? {
    public SimpleBooleanProperty prop1 = new SimpleBooleanProperty();
    public SimpleStringProperty prop2 = new SimpleStringProperty();

    // ** more properties ** //

    private final ObjectBinding<Void> binding = Bindings.createObjectBinding(this::bar, prop1, prop2, prop3, prop4);

    private final Void bar() {
        Optional.of(newValue.prop1.get()).ifPresent(System.out::println);
        Optional.of(newValue.prop2.get()).ifPresent(System.out::println);
        Optional.of(newValue.prop3.get()).ifPresent(System.out::println);
        Optional.of(newValue.prop4.get()).ifPresent(System.out::println);

        return null;
    }
}

绑定本身会监听你,但你必须保留绑定的强引用,否则它将被垃圾收集。