JavaBean包装与JavaFX属性
我想使用JavaFX属性进行UI绑定,但我不希望它们出现在我的模型类中(请参阅在模型类中使用javafx.beans属性 )。 我的模型类有getter和setter,我想根据这些创建属性。 例如,假设一个实例bean
的方法是String getName()
和setName(String name)
,我会写
SimpleStringProperty property = new SimpleStringProperty(bean, "name")
期望property.set("Foobar")
将触发对bean.setName
的调用。 但这似乎不起作用。 我错过了什么?
Simple*Property
类是其对应的Property
抽象类的完整独立实现,并且不依赖于任何其他对象。 因此,例如, SimpleStringProperty
包含一个(私有) String
字段本身,它保存属性的当前值。
您显示的构造函数的参数:
new SimpleStringProperty(bean, "name")
是:
-
bean
:属性所属的bean,如果有的话 -
name
:属性的名称
bean
可以在ChangeListener
的changed(...)
方法中使用,因为您可以检索从属性本身更改的属性的“拥有bean”。 可以类似地使用该name
(如果您具有向多个属性注册的相同侦听器,则可以确定哪个属性已更改:尽管我从不使用此模式)。
因此, SimpleStringProperty
作为对象的可观察属性的典型用法如下所示:
public class Person { private final StringProperty firstName = new SimpleStringProperty(this, "firstName"); public final String getFirstName() { return firstName.get(); } public final void setFirstName(String firstName) { this.firstName.set(firstName); } public StringProperty firstNameProperty() { return firstName ; } // ... other properties, etc }
您正在寻找的function:将现有Java Bean样式属性包装在JavaFX observable属性中是由javafx.beans.property.adapter
包中的类实现的。 所以,例如,你可以做到
StringProperty nameProperty = new JavaBeanStringPropertyBuilder() .bean(bean) .name("name") .build();
调用
nameProperty.set("James");
使用此设置将有效地调用
bean.setName("James");
如果bean支持PropertyChangeListener
,则JavaBeanStringProperty
将使用bean注册PropertyChangeListener
。 对Java Bean的name
属性的任何更改都将由JavaBeanStringProperty
转换为JavaFX属性更改。 因此,如果底层JavaBean支持PropertyChangeListener
,则通过bean更改bean
bean.setName(...);
将导致向JavaBeanStringProperty
注册的任何ChangeListener
(或InvalidationListener
)被通知更改。
因此,例如,如果Bean类是
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; public class Bean { private String name ; private final PropertyChangeSupport propertySupport ; public Bean(String name) { this.name = name ; this.propertySupport = new PropertyChangeSupport(this); } public Bean() { this(""); } public String getName() { return name ; } public String setName(String name) { String oldName = this.name ; this.name = name ; propertySupport.firePropertyChange("name", oldName, name); } public void addPropertyChangeListener(PropertyChangeListener listener) { propertySupport.addPropertyChangeListener(listener); } }
然后是以下代码:
Bean bean = new Bean(); StringProperty nameProperty() = new JavaBeanStringPropertyBuilder() .bean(bean) .name("name") .build(); nameProperty().addListener((obs, oldName, newName) -> System.out.println("name changed from "+oldName+" to "+newName)); bean.setName("James"); System.out.println(nameProperty().get());
将产生输出:
name changed from to James James
如果JavaBean不支持PropertyChangeListener
,则通过bean.setName(...)
对bean的更改不会传播到使用JavaBeanStringProperty
注册的ChangeListener
或InvalidationListener
。
所以,如果豆是简单的
public class Bean { public Bean() { this(""); } public Bean(String name) { this.name = name ; } private String name ; public String getName() { return name ; } public void setName(String name) { this.name = name ; } }
JavaBeanStringProperty无法观察更改,因此调用bean.setName()
永远不会调用更改侦听器。 所以上面的测试代码只会输出
James