如何将TableView列设置为LocalDate并仅通过FXML设置它的值?

时间:2016-05-09 12:28:20

标签: javafx tableview fxml tablecolumn

如何将LocalDate值仅填充到fxml中的列?

我的Controller类中的某个地方:

protected void addPerson(ActionEvent event) {       
    ObservableList<Person> data = tableView.getItems();
    data.add(new Person(firstNameField.getText(),lastNameField.getText(),emailField.getText(),checkBox.isSelected(),Integer.parseInt(numberField.getText()),LocalDate.now()));     
    firstNameField.setText("");
    lastNameField.setText("");
    emailField.setText("");
    checkBox.setSelected(false);
    numberField.setText("0");
    dateField.setText(""+LocalDate.now());

}

人员类:

public class Person {

private final SimpleStringProperty firstName = new SimpleStringProperty("");
private final SimpleStringProperty lastName = new SimpleStringProperty("");
private final SimpleStringProperty email = new SimpleStringProperty("");
private final SimpleBooleanProperty checked = new SimpleBooleanProperty(false);
private final SimpleIntegerProperty alter = new SimpleIntegerProperty();
private final ObjectProperty<LocalDate> date;

...

FXML:......

    <TableColumn prefWidth="75.0" text="Date">
        <cellValueFactory>
            <PropertyValueFactory property="date" />
        </cellValueFactory>
    </TableColumn>
    <TableColumn prefWidth="75.0" text="G" />
</columns>
<items>

    <FXCollections fx:factory="observableArrayList">
         <Person alter="1" checked="false"  
                 email="tester1.test@test.com"  firstName="Tester1"   
                 lastName="Test"/>                                                                      

    </FXCollections>
</items>

我试过了:

<Person alter="1" checked="false" email="tester1.test@test.com" firstName="Tester1" lastName="Test" date="2016.01.01"/> 

但是我得到了一个javafx.fxml.LoadException:

Caused by: java.lang.IllegalArgumentException: Unable to coerce 2016.01.01 to class java.time.LocalDate.
    at com.sun.javafx.fxml.BeanAdapter.coerce(BeanAdapter.java:496)
    at com.sun.javafx.fxml.BeanAdapter.put(BeanAdapter.java:258)
    at com.sun.javafx.fxml.BeanAdapter.put(BeanAdapter.java:54)
    at javafx.fxml.FXMLLoader$Element.applyProperty(FXMLLoader.java:512)
    at javafx.fxml.FXMLLoader$Element.processValue(FXMLLoader.java:363)
    at javafx.fxml.FXMLLoader$Element.processPropertyAttribute(FXMLLoader.java:325)
    at javafx.fxml.FXMLLoader$Element.processInstancePropertyAttributes(FXMLLoader.java:235)
    at javafx.fxml.FXMLLoader$ValueElement.processEndElement(FXMLLoader.java:767)
    at javafx.fxml.FXMLLoader.processEndElement(FXMLLoader.java:2823)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2532)
    ... 13 more

1 个答案:

答案 0 :(得分:2)

FXMLLoader无法从LocalDate初始化String这为您留下2个选项:

使用valueOf + fx:value

在某个类

中实现方法public static LocalDate valueOf(String)
public final class Util {

    private Util() {
    }

    private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy.MM.dd");

    public static LocalDate valueOf(String val) {
        return LocalDate.parse(val, DATE_FORMAT);
    }

    public static String toString(LocalDate date) {
        return date == null ? null : date.format(DATE_FORMAT);
    }

}

并像这样更改你的fxml文件:

<Person alter="1" checked="false" email="tester1.test@test.com" firstName="Tester1" lastName="Test">
    <date>
        <Util fx:value="2016.01.01"/>
    </date>
</Person>

使用BuilderFactory

保持fxml不变,并使用BuilderFactory创建Person的自定义Builder。此构建器具有Person的每个属性的getter / setter,它们委托产品的相应方法,但需要特殊处理的属性除外。对于这些属性,它还会转换为/ String

public class PersonBuilder implements Builder<Person> {

    private final Person product = new Person();

    @Override
    public Person build() {
        return product;
    }

    public void setAlter(int value) {
        product.setAlter(value);
    }

    public void setDate(String value) {
        product.setDate(Util.valueOf(value));
    }

    public void setEmail(String value) {
        product.setEmail(value);
    }

    ...

    public int getAlter() {
        return product.getAlter();
    }

    public String getDate() {
        return Util.toString(product.getDate());
    }

    public String getEmail() {
        return product.getEmail();
    }

    ...

}
FXMLLoader loader = new FXMLLoader(getClass().getResource("person.fxml"));
loader.setBuilderFactory(new BuilderFactory() {

    private final BuilderFactory fallback = new JavaFXBuilderFactory();

    @Override
    public Builder<?> getBuilder(Class<?> type) {
        return type == Person.class ? new PersonBuilder() : fallback.getBuilder(type);
    }

});

loader.load();