java属性绑定_J1003.JavaFX属性和绑定01——简单对象

JavaBean扩展

为了实现基于JavaBean的属性、绑定以及事件机制,JavaFX对JavaBean进行了扩展,JavaBean不再是POJO,显得更加“重量级”一些。

JavaFX属性

JavaFX为Java通用包装类提供了通用的属性包装类,以实现事件监听、数据绑定等功能。如下表:

5f57c3a3b1d98498e5ed61cfefca0409.png

所有这些类都是Observable接口的实现类,以上只是示例了部分,详细类见javafx.beans.property包下。

JavaFX中的Property体系没有实现Serializable接口,所以无法跨JVM传递。也就是说,应用服务器无法向客户端返回这类信息;客户端也无法将这类信息传递给应用服务器。这给我们开发B/S应用系统造成了困扰。

由于需要进行值监听等操作,所以JavaFX的Property对空属性比较敏感,我们在写代码时要特别关注。

JavaFX Property对空属性的敏感

如果Property没有初始化,则对其操作时会报出空指针。

packagecom.lirong.javafx.demo.j1003;importjavafx.beans.property.StringProperty;public classDemoFXBean {/*** 编码*/

privateStringProperty test_code;/*** 名称*/

privateStringProperty test_name;publicString getTest_code() {returntest_code.get();

}publicStringProperty test_codeProperty() {returntest_code;

}public voidsetTest_code(String test_code) {this.test_code.set(test_code);

}publicString getTest_name() {returntest_name.get();

}publicStringProperty test_nameProperty() {returntest_name;

}public voidsetTest_name(String test_name) {this.test_name.set(test_name);

}

}

我们可以看到,JavaFX Bean中,每个属性都会有三个方法:

1、getter值的方法,如getTest_code();

2、setter值的方法,如setTest_code(String test_code);

3、获取属性的方法,如test_codeProperty();

当我们使用以下代码进行测试时:

packagecom.lirong.javafx.demo.j1003;public classTestFXBean {public static voidmain(String[] args) {

DemoFXBean demoFXBean= newDemoFXBean();

demoFXBean.setTest_code("TestCode");

}

}

控制台打印如下错误信息:

122a8fe735cc631f05096fb59d6fb138.png

从DemoFXBean的代码可以看出,对属性操作的三个方法,都是基于Property进行的。所以如果不初始化Property,get、set时,就会发生空指针异常。

一个简单的JavaFX Bean

当Bean中某个字段值发生变化时,打印信息并修改其它值。我们把DemoFXBean修改一下:

packagecom.lirong.javafx.demo.j1003;importjavafx.beans.property.SimpleStringProperty;importjavafx.beans.property.StringProperty;public classDemoFXBean {/*** 编码*/

private StringProperty test_code = newSimpleStringProperty();/*** 名称*/

private StringProperty test_name = newSimpleStringProperty();publicDemoFXBean() {super();

initListener();

}private voidinitListener() {//监听test_code属性的变化,同时修改其它属性值

test_codeProperty().addListener((observable, oldValue, newValue)->{

System.out.println(String.format("test_code changed. oldValue=%s, newValue=%s", oldValue, newValue));//设置其它属性值

setTest_name(String.format("%s 的名称", newValue));

});//监听test_name属性的变化

test_nameProperty().addListener((observable, oldValue, newValue)->{

System.out.println(String.format("test_name changed. oldValue=%s, newValue=%s", oldValue, newValue));

});

}publicString getTest_code() {returntest_code.get();

}publicStringProperty test_codeProperty() {returntest_code;

}public voidsetTest_code(String test_code) {this.test_code.set(test_code);

}publicString getTest_name() {returntest_name.get();

}publicStringProperty test_nameProperty() {returntest_name;

}public voidsetTest_name(String test_name) {this.test_name.set(test_name);

}

}

主要修改了以下内容:

1、初始化Property;

2、增加监听器;

再运行TestFXBean测试类时,控制台打印如下信息:

a6234f10a62fed4d50e90204b729e5c9.png

可以看到,两个监听器都产生了预期的动作。

JavaBean的属性监听机制

如前所述,JavaFX的Property由于没有实现序列化,所以无法跨JVM传递。所以我们要有一种JavaFX Bean和JavaBean之间的包装、转换机制,使Bean能够跨JVM。这种机制是我们后续在B/S框架中使用JavaFX的必要准备。

我们的方法是:改造javaBean,通过改造后的JavaBean包装生成JavaFX Bean,并使JavaBean和JavaFX Bean之间的属性实现双向联动。

增加一个DemoJavaBean,为其实现属性监听:

packagecom.lirong.javafx.demo.j1003;importjava.beans.PropertyChangeListener;importjava.beans.PropertyChangeSupport;importjava.io.Serializable;public class DemoJavaBean implementsSerializable {private static final long serialVersionUID = -6499105304636177551L;protected final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);/*** 编码*/

privateString test_code;/*** 名称*/

privateString test_name;publicString getTest_code() {returntest_code;

}public voidsetTest_code(String test_code) {final String oldValue = this.test_code;this.test_code =test_code;

propertyChangeSupport.firePropertyChange("test_code", oldValue, this.test_code);

}publicString getTest_name() {returntest_name;

}public voidsetTest_name(String test_name) {final String oldValue = this.test_name;this.test_name =test_name;

propertyChangeSupport.firePropertyChange("test_name", oldValue, this.test_name);

}public voidaddPropertyChangeListener(PropertyChangeListener listener) {

propertyChangeSupport.addPropertyChangeListener(listener);

}public voidremovePropertyChangeListener(PropertyChangeListener listener) {

propertyChangeSupport.removePropertyChangeListener(listener);

}

}

需要注意的是:

1、为DemoJavaBean增加了PropertyChangeSupport属性,并增加了两个相关方法addPropertyChangeListener和removePropertyChangeListener;

2、在setter中,产生属性变化事件,并传递修改前、修改后的值;

3、该类实现了序列化接口;

增加DemoJavaFXBean类:

packagecom.lirong.javafx.demo.j1003;importjavafx.beans.property.SimpleStringProperty;importjavafx.beans.property.StringProperty;importjavafx.beans.property.adapter.JavaBeanStringPropertyBuilder;public classDemoJavaFXBean {privateDemoJavaBean javaBean;/*** 编码*/

private StringProperty test_code = newSimpleStringProperty();/*** 名称*/

private StringProperty test_name = newSimpleStringProperty();/*** DemoJavaFXBean的构造器,必须传入一个DemoJavaBean,用于初始化属性

*

*@paramjavaBean*/

publicDemoJavaFXBean(DemoJavaBean javaBean) {super();this.javaBean =javaBean;

initProperty();

}/*** 通过 DemoJavaBean 初始化 DemoJavaFXBean 的属性*/

private voidinitProperty() {//根据JavaBean初始化JavaFX Bean的属性

try{/*编码*/test_code= JavaBeanStringPropertyBuilder.create().bean(this.javaBean).name("test_code").build();/*名称*/test_name= JavaBeanStringPropertyBuilder.create().bean(this.javaBean).name("test_name").build();

}catch(Exception ex) {throw newRuntimeException(ex);

}

}publicDemoJavaBean getJavaBean() {returnjavaBean;

}public voidsetJavaBean(DemoJavaBean javaBean) {this.javaBean =javaBean;//设置JavaBean后,需要重新初始化JavaFX Bean

initProperty();

}publicString getTest_code() {returntest_code.get();

}publicStringProperty test_codeProperty() {returntest_code;

}public voidsetTest_code(String test_code) {this.test_code.set(test_code);

}publicString getTest_name() {returntest_name.get();

}publicStringProperty test_nameProperty() {returntest_name;

}public voidsetTest_name(String test_name) {this.test_name.set(test_name);

}

}

需要注意的是:

1、DemoJavaFXBean的构造器,授受一个DemoJavaBean,以进行本类的属性初始化;

2、通过initProperty方法进行属性初始化;

3、该类没有实现序列化接口;

测试类TestJavaBeanFX,主要用于测试属性修改是否在JavaFX Bean和JavaBean之间自动联动:

packagecom.lirong.javafx.demo.j1003;public classTestJavaBeanFX {public static voidmain(String[] args) {

DemoJavaBean demoJavaBean= newDemoJavaBean();

DemoJavaFXBean demoJavaFXBean= newDemoJavaFXBean(demoJavaBean);final String strFormatter = "JavaFX Bean PropertyName=%s, PropertyValue=%s; Java Bean PropertyName=%s, PropertyValue=%s";//修改Java Bean的属性,查看JavaFX Bean相应的属性是否同步修改了

demoJavaFXBean.getJavaBean().setTest_code("TestCode");

System.out.println(String.format(strFormatter,"Code", demoJavaFXBean.getTest_code(), "Code", demoJavaFXBean.getJavaBean().getTest_code()));//修改JavaFX Bean的属性,查看Java Bean相应的属性是否同步修改了

demoJavaFXBean.setTest_name("TestName");

System.out.println(String.format(strFormatter,"Name", demoJavaFXBean.getTest_name(), "Name", demoJavaFXBean.getJavaBean().getTest_name()));

}

}

控制台输出以下信息:

219ea4e5645a034b2df412400e0fe6dd.png

我们可以看到,修改JavaFX Bean或Java Bean的属性值,将同步两个Bean的属性值。

需要注意的是:

1、必须为JavaBean实现属性变化监听事件机制;

2、通过JavaBean构造JavaFX Bean,并实现属性初始化;

通过本例也可以进一步看出:在JavaFX属性机制中,属性不可为空,属性值可以为空。我们在TestJavaBeanFX类中实例化DemoJavaBean时,没有为它的任何属性赋值。但在初始化DemoJavaFXBean时,通过JavaFX的PropertyBuilder产生属性值为空的非空属性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值