JavaBean包装与JavaFX属性 [英] JavaBean wrapping with JavaFX Properties
问题描述
我想使用JavaFX属性进行UI绑定,但我不希望它们出现在我的模型类中(参见在模型类中使用javafx.beans属性)。我的模型类有getter和setter,我想根据这些创建属性。例如,假设一个实例 bean
,方法为 String getName()
和 setName(String name) )
,我会写
I want to use JavaFX properties for UI binding, but I don't want them in my model classes (see Using javafx.beans properties in model classes). My model classes have getters and setters, and I want to create properties based on those. For example, assuming an instance bean
with methods String getName()
and setName(String name)
, I would write
SimpleStringProperty property = new SimpleStringProperty(bean, "name")
期待 property.set(Foobar)
会触发对 bean.setName
的调用。但这似乎不起作用。我缺少什么?
expecting that property.set("Foobar")
would trigger a call to bean.setName
. But this doesn't seem to work. What am I missing?
推荐答案
简单*属性
类已满,它们对应的 Property
抽象类的独立实现,并且不依赖于任何其他对象。因此,例如, SimpleStringProperty
包含一个(私有) String
字段本身,它保存属性的当前值。
The Simple*Property
classes are full, standalone implementations of their corresponding Property
abstract classes, and do not rely on any other object. So, for example, SimpleStringProperty
contains a (private) String
field itself which holds the current value of the property.
您显示的构造函数的参数:
The parameters to the constructor you showed:
new SimpleStringProperty(bean, "name")
是:
-
bean
:属性所属的bean,如果有的话 -
name
:属性的名称
bean
: the bean to which the property belongs, if anyname
: the name of the property
bean
在 ChangeListener
的更改(...)
方法中非常有用,因为您可以检索拥有从物业本身改变的财产的豆。可以类似地使用名称
(如果您使用多个属性注册了相同的侦听器,则可以确定哪个属性已更改:尽管我从不使用此模式)。
The bean
can be useful in a ChangeListener
's changed(...)
method as you can retrieve the "owning bean" of the property that changed from the property itself. The name
can be used similarly (if you have the same listener registered with multiple properties, you can figure out which property changed: though I never use this pattern).
因此,作为对象的可观察属性的 SimpleStringProperty
的典型用法如下所示:
So a typical use of a SimpleStringProperty
as an observable property of an object looks like:
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
}
您正在寻找的功能:将现有Java Bean样式属性包装在JavaFX observable属性中是由 javafx.beans.property.adapter中的类实现的
包。所以,例如,你可以做
The functionality you are looking for: to wrap an existing Java Bean style property in a JavaFX observable property is implemented by classes in the javafx.beans.property.adapter
package. So, for example, you could do
StringProperty nameProperty = new JavaBeanStringPropertyBuilder()
.bean(bean)
.name("name")
.build();
致电
nameProperty.set("James");
使用此设置将有效调用
bean.setName("James");
如果bean支持 PropertyChangeListener
s, JavaBeanStringProperty
将使用bean注册 PropertyChangeListener
。对Java Bean的 name
属性的任何更改都将由 JavaBeanStringProperty
转换为JavaFX属性更改。因此,如果底层JavaBean支持 PropertyChangeListener
s,则通过
If the bean supports PropertyChangeListener
s, the JavaBeanStringProperty
will register a PropertyChangeListener
with the bean. Any changes to the name
property of the Java Bean will be translated by the JavaBeanStringProperty
into JavaFX property changes. Consequently, if the underlying JavaBean supports PropertyChangeListener
s, then changes to the bean via
bean.setName(...);
将导致任何 ChangeListener
s(或 InvalidationListener
s)注册 JavaBeanStringProperty
收到更改通知。
will result in any ChangeListener
s (or InvalidationListener
s) registered with the JavaBeanStringProperty
being notified of the change.
因此,例如,如果Bean类是
So, for example, if the Bean class is
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
s,然后通过 bean.setName(...)
更改为bean不会传播到 ChangeListener
s或使用
。 JavaBeanStringProperty
注册的InvalidationListener
If the JavaBean does not support PropertyChangeListener
s, then changes to the bean via bean.setName(...)
will not propagate to ChangeListener
s or InvalidationListener
s registered with the JavaBeanStringProperty
.
因此,如果bean只是
So if the bean is simply
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()
永远不会调用更改侦听器。所以上面的测试代码只会输出
The JavaBeanStringProperty would have no way to observe the change, so the change listener would never be invoked by a call to bean.setName()
. So the test code above would simply output
James
这篇关于JavaBean包装与JavaFX属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!