JavaBean包装与JavaFX属性

时间:2014-05-07 15:32:38

标签: java model-view-controller javafx model javabeans

我想将JavaFX属性用于UI绑定,但我不希望它们出现在我的模型类中(请参阅Using javafx.beans properties in model classes)。我的模型类有getter和setter,我想根据这些创建属性。例如,假设一个实例bean包含方法String getName()setName(String name),我会写

 SimpleStringProperty property = new SimpleStringProperty(bean, "name")

期望property.set("Foobar")会触发对bean.setName的调用。但这似乎不起作用。我错过了什么?

1 个答案:

答案 0 :(得分:44)

Simple*Property类是对应的Property抽象类的完整独立实现,不依赖于任何其他对象。因此,例如,SimpleStringProperty包含一个(私有)String字段本身,它保存属性的当前值。

您显示的构造函数的参数:

new SimpleStringProperty(bean, "name")

是:

  • bean:属性所属的bean,如果有的话
  • name:属性的名称

beanChangeListener的{​​{1}}方法中非常有用,因为您可以检索"拥有的bean"从物业本身改变的财产。可以类似地使用changed(...)(如果您使用多个属性注册了相同的侦听器,则可以确定哪个属性已更改:尽管我从不使用此模式)。

因此,name作为对象的可观察属性的典型用法如下所示:

SimpleStringProperty

您正在寻找的功能:将现有Java Bean样式属性包装在JavaFX observable属性中是由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 } 包中的类实现的。所以,例如,你可以做到

javafx.beans.property.adapter

致电

StringProperty nameProperty = new JavaBeanStringPropertyBuilder()
        .bean(bean)
        .name("name")
        .build();

使用此设置将有效地调用

nameProperty.set("James");

如果bean支持bean.setName("James"); ,则PropertyChangeListener将向bean注册JavaBeanStringProperty。对Java Bean的PropertyChangeListener属性的任何更改都将由name转换为JavaFX属性更改。因此,如果底层JavaBean支持JavaBeanStringProperty,则通过

更改bean
PropertyChangeListener

将导致向bean.setName(...); 注册的任何ChangeListener s(或InvalidationListener s)通知此更改。

因此,例如,如果Bean类是

JavaBeanStringProperty

然后是以下代码:

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());

如果JavaBean不支持name changed from to James James ,那么通过PropertyChangeListener对bean的更改将不会传播到bean.setName(...)ChangeListener注册的InvalidationListener }}

所以如果bean只是

JavaBeanStringProperty

JavaBeanStringProperty无法观察更改,因此调用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 ; } } 永远不会调用更改侦听器。所以上面的测试代码只会输出

bean.setName()