ObservableValue更改侦听器:如何访问

时间:2015-11-25 09:06:27

标签: javafx changelistener

我是JavaFX的新手,已经开始转换用Swing编写的自定义组件。作为一种最佳实践,我总是检查目标对象的侦听器中是否已包含事件侦听器(PropertyChangeListener,MouseListener,ActionListener等),以确保同一个侦听器不会被添加两次。我试图用JavaFX做同样的事情,但无法找到任何方法来访问监听器列表(例如,运行list.contains(监听器)检查)。

我在找一些不存在的东西吗?如果是这样,是否有一些很好的理由说明为什么JavaFX不包含此功能(恕我直言)?

感谢您的反馈!

1 个答案:

答案 0 :(得分:0)

公共API中没有机制可以访问JavaFX中属性的侦听器列表。

我不确定我是否真的认为需要这个。您的代码可以控制添加和删除侦听器的时间,因此您基本上始终会知道"何时添加了听众。从更广泛的意义上讲,您的UI或UI组件始终是某种形式的数据的表示,因此,无论是否注册了侦听器,都只是这些数据的函数。

举一个具体的例子,考虑评论中引用的用例:

public class CustomComponent extends BorderPane {

    private final Button button = new Button("Button");
    private final TextField textField = new TextField();

    private final ObjectProperty<Orientation> orientation = new SimpleObjectProperty<>();

    public ObjectProperty<Orientation> orientationProperty() {
        return orientation ;
    }

    public final Orientation getOrientation() {
        return orientationProperty().get();
    }

    public final void setOrientation(Orientation orientation) {
        orientationProperty().set(orientation);
    }

    public CustomControl(Orientation orientation) {
        setCenter(textField);

        ChangeListener<Number> widthBindingListener = (obs, oldWidth, newWidth) ->
            button.setPrefWidth(newWidth.doubleValue());

        orientationProperty().addListener((obs, oldOrientation, newOrientation) -> {
            if (newOrientation == Orientation.HORIZONTAL) {
                textField.widthProperty().removeListener(widthBindingListener);
                button.setPrefWidth(Control.USE_COMPUTED_SIZE);
                setTop(null);
                setLeft(button);
            } else {
                textField.widthProperty().addListener(widthBindingListener);
                button.setPrefWidth(textField.getWidth());
                setLeft(null);
                setTop(button);
            }
        }

        setOrientation(orientation);

    }

    public CustomControl() {
        this(Orientation.VERTICAL);
    }

    // other methods etc....
}

在此示例中,您可能只使用绑定而不是侦听器:

button.prefWidthProperty().bind(Bindings
    .when(orientationProperty().isEqualTo(Orientation.HORIZONTAL))
    .then(Control.USE_COMPUTED_SIZE)
    .otherwise(textField.widthProperty()));

但这并没有证明这个概念......

请注意,与@Clemens注释一样,您始终可以确保只使用惯用语注册一次侦听器:

textField.widthProperty().removeListener(widthBindingListener);
textField.widthProperty().addListener(widthBindingListener);

但是在我看来这不是一个很好的练习:removeListener涉及遍历监听器列表(如果还没有添加,整个< / em>监听器列表)。此迭代是不必要的,因为该信息已在其他地方可用。