使用 JavaFX 属性包装的 JavaBean [英] 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?
推荐答案
Simple*Property
类是其对应的 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
的 changed(...)
方法中很有用,因为您可以检索拥有的 bean"从属性本身改变的属性.name
可以类似地使用(如果你有同一个监听器注册了多个属性,你可以找出哪个属性发生了变化:虽然我从来没有使用过这种模式).
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 可观察属性中是由 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");
使用此设置将有效地调用
with this setup will effectively cause a call to
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(...);
将导致向 JavaBeanStringProperty
注册的任何 ChangeListener
s(或 InvalidationListener
s)被通知更改.
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
code>s 或 InvalidationListener
s 注册到 JavaBeanStringProperty
.
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
这篇关于使用 JavaFX 属性包装的 JavaBean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!