目前,我想要做的是使用JAXB生成的POJO将每个Java属性绑定到JavaFX组件。为此,我继续如下:
以下是我工厂的样本:
public static Map<Field, Node> createComponents(Object obj) throws NoSuchMethodException
{
Map<Field, Node> map = new LinkedHashMap<Field, Node>();
for (final Field field : obj.getClass().getDeclaredFields())
{
@SuppressWarnings("rawtypes")
Class fieldType = field.getType();
if (fieldType.equals(boolean.class) || (fieldType.equals(Boolean.class))) //Boolean
{
map.put(field, createBool(obj, field));
}
else if (fieldType.equals(int.class) || (fieldType.equals(Integer.class))) //Integer
{
map.put(field, createInt(obj, field));
}
else if (fieldType.equals(BigInteger.class)) //BigInteger
{
map.put(field, createBigInt(obj, field));
}
else if (fieldType.equals(long.class) || fieldType.equals(Long.class)) //Long
{
map.put(field, createLong(obj, field));
}
else if (fieldType.equals(String.class)) //String
{
map.put(field, createString(obj, field));
}
...
}
return map;
}
public static Node createBool(Object obj, final Field field) throws NoSuchMethodException
{
System.out.println(field.getType().getSimpleName() + " spotted");
JavaBeanBooleanProperty boolProperty = JavaBeanBooleanPropertyBuilder.create().bean(obj).name(field.getName()).build();
boolProperty.addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean arg2)
{
prettyPrinter(field, arg1, arg2);
}
});
CheckBox cb = new CheckBox();
cb.setText(" : " + field.getName());
cb.selectedProperty().bindBidirectional(boolProperty);
return cb;
}
public static Node createInt(Object obj, final Field field) throws NoSuchMethodException
{
System.out.println(field.getType().getSimpleName() + " spotted");
JavaBeanIntegerProperty intProperty = JavaBeanIntegerPropertyBuilder.create().bean(obj).name(field.getName()).build();
StringProperty s = new SimpleStringProperty();
StringConverter sc = new IntegerStringConverter();
Bindings.bindBidirectional(s, intProperty, sc);
s.addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> arg0, String arg1, String arg2)
{
prettyPrinter(field, arg1, arg2);
}
});
TextField tf = new TextField();
tf.textProperty().bindBidirectional(s);
return tf;
}
所以,我遇到的问题是:在大多数情况下,当我更改时,例如,一个textField,POJO属性不会注意到。但在某些情况下,当我更改POJO中字段的顺序时,每个监听器都会注意到任何变化。
以下是使用后面的 Personne 类(当前有效)的GUI的示例
public class Personne
{
private int taille;
private Boolean lol;
private long pointure;
private BigInteger age;
private boolean zombified;
private String name;
private PropertyChangeSupport _changeSupport = new PropertyChangeSupport(this);
public Boolean getLol()
{
return this.lol;
}
public long getPointure()
{
return this.pointure;
}
public int getTaille()
{
return taille;
}
public boolean getZombified()
{
return zombified;
}
public BigInteger getAge()
{
return age;
}
public String getName()
{
return name;
}
public void setPointure(long pointure)
{
final long prev = this.pointure;
this.pointure = pointure;
_changeSupport.firePropertyChange("pointure", prev, pointure);
}
public void setTaille(int taille)
{
final int prev = this.taille;
this.taille = taille;
_changeSupport.firePropertyChange("taille", prev, taille);
}
public void setAge(BigInteger age)
{
final BigInteger prev = this.age;
this.age = age;
_changeSupport.firePropertyChange("age", prev, age);
}
public void setName(String name)
{
final String prev = this.name;
this.name = name;
_changeSupport.firePropertyChange("name", prev, name);
}
public void setLol(Boolean lol)
{
final Boolean prev = this.lol;
this.lol = lol;
_changeSupport.firePropertyChange("lol", prev, lol);
}
public void setZombified(boolean zombified)
{
final boolean prev = this.zombified;
this.zombified = zombified;
_changeSupport.firePropertyChange("zombified", prev, zombified);
}
public void addPropertyChangeListener(final PropertyChangeListener listener)
{
_changeSupport.addPropertyChangeListener(listener);
}
}
我想知道财产订单如何影响这样的绑定。此外,我注意到如果我想返回包裹在HBox中的节点,则绑定不再起作用。
我认为我做错了,但我无法弄清楚是什么。
答案 0 :(得分:1)
您的JavaBeanIntegerProperty和JavaBeanBooleanProperty过早被垃圾收集。
方法Property.bind(Observable)
使属性保持对observable的强引用,但 observable只保存对属性的弱引用!(它只在Observable上注册一个Listener有一个WeakReference回到Property)。同样,当您致电Bindings.bindBidirectional(Property, Property)
时,两个属性都会相互之间保持弱引用!这是一个非常重要的细节,很难在文档中找到。
如果您只与JavaFX对象进行交互,这不是问题,因为JavaFX对象自然拥有对其所有属性的强引用。但是如果您使用JavaBeanIntegerProperty从遗留对象包装bean属性,那么bean不会持有对JavaBeanIntegerProperty的强引用,因此在gc之后,Property将消失并停止更新bean!我认为这是JavaBeanIntegerProperty中的设计错误。
解决方案是将JavaBeanIntegerProperty分配给一个字段并存储它,只要您希望绑定继续更新bean。
或者,您可以编写自己的Property子类来执行某些操作,以确保从Bean到Property存在强引用(例如,addPropertyChangeListener将直接监听bean)。