我是JavaFX的新手,已经开始转换用Swing编写的自定义组件。作为一种最佳实践,我总是检查目标对象的侦听器中是否已包含事件侦听器(PropertyChangeListener,MouseListener,ActionListener等),以确保同一个侦听器不会被添加两次。我试图用JavaFX做同样的事情,但无法找到任何方法来访问监听器列表(例如,运行list.contains(监听器)检查)。
我在找一些不存在的东西吗?如果是这样,是否有一些很好的理由说明为什么JavaFX不包含此功能(恕我直言)?
感谢您的反馈!
答案 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>监听器列表)。此迭代是不必要的,因为该信息已在其他地方可用。