JavaBean包装与JavaFX属性 [英] JavaBean wrapping with JavaFX Properties

查看:171
本文介绍了JavaBean包装与JavaFX属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用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 any
  • name: 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 PropertyChangeListeners, 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 PropertyChangeListeners, then changes to the bean via

bean.setName(...);

将导致任何 ChangeListener s(或 InvalidationListener s)注册 JavaBeanStringProperty 收到更改通知。

will result in any ChangeListeners (or InvalidationListeners) 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 PropertyChangeListeners, then changes to the bean via bean.setName(...) will not propagate to ChangeListeners or InvalidationListeners 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆