我有一個經典的JavaBean,它將與JavaFX TextField綁定。Javafx中的雙向綁定StringProperty不能反向工作
public class Cell {
public static final String CELL_VALUE = "Cell.Value";
private Optional<Integer> value;
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
public Optional<Integer> getValue() {
return value;
}
public void setValue(Optional<Integer> value) {
Optional<Integer> old = this.value;
this.value = value;
this.pcs.firePropertyChange(CELL_VALUE, old, value);
}
/**
* The values must be from 1 to 9. 0 or null will be converted to Option.none.
*/
public void setValue(int value) {
this.setValue(Optional.of(value));
}
}
另外我創建了一個字符串轉換子類:
import java.util.Optional;
import javafx.util.StringConverter;
public class CellValueStringConverter extends StringConverter<Optional<Integer>> {
@Override
public String toString(Optional<Integer> value) {
System.out.printf("toString() : %s%n", value);
return value.isPresent()? String.valueOf(value.get()): "";
}
@Override
public Optional<Integer> fromString(String string) {
System.out.printf("fromString() : %s%n", string);
if(string.matches("^[1-9]$")) {
return Optional.of(Integer.valueOf(string));
}
if(string.isEmpty() || string.matches("^(|0)$")) {
return Optional.empty();
}
throw new IllegalArgumentException("Illegal value for a Cell: " + string);
}
}
在控制器類,前主級變得可見,我發細胞值和TextField之間的結合:
ObjectProperty<Optional<Integer>> valueProperty = JavaBeanObjectPropertyBuilder.create().bean(cell)
.name("value").build();
final StringProperty textProperty = textField.textProperty();
// Binding ...
textProperty.bindBidirectional(valueProperty, new CellValueStringConverter());
textField.addEventFilter(MouseEvent.MOUSE_CLICKED, me -> {
if (me.getClickCount() == 2) {
cell.setValue(random.nextInt(8) + 1);
}
});
textProperty.addListener(
(ov, oldValue, newValue) -> System.out.printf("textProperty : %s -> %s%n", oldValue, newValue));
valueProperty.addListener(
(ov, oldValue, newValue) -> System.out.printf("valueProperty: %s -> %s%n", oldValue, newValue));
cell.addPropertyChangeListener(
evt -> System.out.printf("cell : %s -> %s%n", evt.getOldValue(), evt.getNewValue()));
當我開始申請時,我收到消息toString() : Optional.empty
。當我輸入一個值(比方說,「4」)在一個空的文本字段,這些信息將顯示:
fromString() : 4
cell : Optional.empty -> Optional[4]
valueProperty: Optional.empty -> Optional[4]
textProperty : -> 4
如果鍵入「8」,在此TextField我得到這個:
fromString() :
cell : Optional[4] -> Optional.empty
valueProperty: Optional[4] -> Optional.empty
textProperty : 4 ->
fromString() : 8
cell : Optional.empty -> Optional[8]
valueProperty: Optional.empty -> Optional[8]
textProperty : -> 8
最後,如果我輸入「0」,單元格將變爲空:
fromString() :
cell : Optional[8] -> Optional.empty
valueProperty: Optional[8] -> Optional.empty
textProperty : 8 ->
到目前爲止,這麼好。但是,如果雙擊TextField,而不是替換文本,則什麼都不會發生。假設單元格的值(和texfField)爲4。當我雙擊,我得到這個消息:
cell : Optional[4] -> Optional[8]
然而,文本框會繼續帶出「4」。未顯示CellValueStringConverter.toString()
中的消息。
假設,當我將單元格值包裝在ObjectProperty
(JavaBeanObjectPropertyBuilder.create().bean(cell).name("value").build()
)中時,它應該觀察值屬性中的所有更改。但是沒有發生。這裏缺少什麼?
感謝,
拉斐爾·阿豐索