如何处理Property<T>、更改监听器和属性的初始化?

ski*_*iwi 5 java javafx properties listener

我正在使用 JavaFX 的Property<T>类,我对结果非常满意,缩小的示例代码:

public CircularListCursor<E> {
    private final Property<E> elementProperty;

    public CircularListCursor() {
        this.elementProperty = new SimpleObjectProperty(/*some value*/);
    }

    //various methods that call elementProperty.setValue(/*some value*/);
}
Run Code Online (Sandbox Code Playgroud)

用法:

private final CircularListCursor<SelectionData> selectionDataCursor;

...

selectionDataCursor.elementProperty().addListener((observableValue, oldValue, newValue) -> {
    oldValue.getLabel().setStyle("-fx-text-fill: black");
    newValue.getLabel().setStyle("-fx-text-fill: red");
});
Run Code Online (Sandbox Code Playgroud)

现在这几乎可以完美地工作,但它不会在对象的构造时触发。它以这种方式工作是合乎逻辑的,因为该属性在构造期间尚未绑定,因此也不能触发任何更改事件。

但我确实希望在构造过程中收到初始值的通知,以允许干净的代码,有没有办法做到这一点?

isn*_*bad 4

JavaFX 中没有直接的解决方案。

尽管如此,您可以通过将侦听器代码移动到私有事件处理程序方法中来使事情变得更容易/更清晰。然后可以在构造结束时调用此方法一次以初始化对象状态。借助 Java 8 lambda 表达式,您可以直接使用对事件处理程序方法的方法引用作为侦听器:

// register event handler method    
selectionDataCursor.elementProperty().addListener(this::onElementChanged);

// call listener once for initialization:
onElementChanged(selectionDataCursor.elementProperty(), null, selectionDataCursor.getElement());

...

// event handler method
private void onElementChanged(ObservableValue<? extends E> observableValue, E oldValue, E newValue) {
    if (oldValue != null) oldValue.getLabel().setStyle("-fx-text-fill: black");
    if (newValue != null) newValue.getLabel().setStyle("-fx-text-fill: red");
}
Run Code Online (Sandbox Code Playgroud)

旁注:通过方法引用构建的侦听器无法再删除。更具体地说,以下代码不会删除侦听器,因为this::onElementChanged每次都会创建一个与已注册的侦听器不同的新侦听器:

selectionDataCursor.elementProperty().removeListener(this::onElementChanged);
Run Code Online (Sandbox Code Playgroud)

  • +1 提及引用侦听器删除的方法。但是,如果声明了侦听器(即使作为方法引用),则可以删除它们,例如: private ChangeListener exampleListener = this::onElementChanged; (2认同)