Vaadin Grid:如何在基于行的编辑器中使用带有LocalTime字段的bean?

时间:2016-08-10 00:58:08

标签: java vaadin vaadin7 vaadin-grid

当我尝试使用基于行的编辑器(setEditorEnabled(true),Buffered Mode)时,我收到错误:

Caused by: com.vaadin.data.util.converter.Converter$ConversionException: Unable to convert value of type java.time.LocalTime to presentation type class java.lang.String. No converter is set and the types are not compatible.
    at com.vaadin.data.util.converter.ConverterUtil.convertFromModel(ConverterUtil.java:116) ~[vaadin-server-7.6.8.jar:7.6.8]

网格初始化:

BeanItemContainer<MealTo> container = new BeanItemContainer<>(MealTo.class);
Grid grid = new Grid();
grid.setContainerDataSource(container);
grid.setEditorEnabled(true);
grid.setSelectionMode(Grid.SelectionMode.NONE);

grid.getColumn("time")
        .setMinimumWidth(100)
        .setConverter(new StringToLocalTimeConverter())
        .setResizable(false);

...

转换器:

public class StringToLocalTimeConverter implements Converter<String, LocalTime> {

    public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm");

    @Override
    public LocalTime convertToModel(String value, Class<? extends LocalTime> targetType, Locale locale) throws ConversionException {
        return LocalTime.parse(value, TIME_FORMATTER);
    }

    @Override
    public String convertToPresentation(LocalTime value, Class<? extends String> targetType, Locale locale) throws ConversionException {
        return value.format(TIME_FORMATTER);
    }

    @Override
    public Class<LocalTime> getModelType() {
        return LocalTime.class;
    }

    @Override
    public Class<String> getPresentationType() {
        return String.class;
    }
}

有谁知道如何解决这个问题? 感谢

1 个答案:

答案 0 :(得分:3)

我尝试了同样的问题,过滤/相关的堆栈跟踪

com.vaadin.data.Buffered$SourceException: null
    at com.vaadin.ui.AbstractField.setPropertyDataSource(AbstractField.java:665) ~[vaadin-server-7.6.8.jar:7.6.8]
    at com.vaadin.data.fieldgroup.FieldGroup.bind(FieldGroup.java:278) ~[vaadin-server-7.6.8.jar:7.6.8]
    at com.vaadin.data.fieldgroup.FieldGroup.buildAndBind(FieldGroup.java:1190) ~[vaadin-server-7.6.8.jar:7.6.8]
    at com.vaadin.data.fieldgroup.FieldGroup.buildAndBind(FieldGroup.java:1168) ~[vaadin-server-7.6.8.jar:7.6.8]
    at com.vaadin.data.fieldgroup.FieldGroup.buildAndBind(FieldGroup.java:1150) ~[vaadin-server-7.6.8.jar:7.6.8]
    at com.vaadin.ui.Grid.getEditorField(Grid.java:6752) ~[vaadin-server-7.6.8.jar:7.6.8]
    at com.vaadin.ui.Grid.doEditItem(Grid.java:6805) ~[vaadin-server-7.6.8.jar:7.6.8]
    at com.vaadin.ui.Grid$4.doBind(Grid.java:4772) ~[vaadin-server-7.6.8.jar:7.6.8]
    at com.vaadin.ui.Grid$4.bind(Grid.java:4761) ~[vaadin-server-7.6.8.jar:7.6.8]
    ... 40 irrelevant lines removed
Caused by: com.vaadin.data.util.converter.Converter$ConversionException: Unable to convert value of type java.time.LocalTime to presentation type class java.lang.String. No converter is set and the types are not compatible.
    at com.vaadin.data.util.converter.ConverterUtil.convertFromModel(ConverterUtil.java:116) ~[vaadin-server-7.6.8.jar:7.6.8]
    at com.vaadin.ui.AbstractField.convertFromModel(AbstractField.java:736) ~[vaadin-server-7.6.8.jar:7.6.8]
    at com.vaadin.ui.AbstractField.convertFromModel(AbstractField.java:721) ~[vaadin-server-7.6.8.jar:7.6.8]
    at com.vaadin.ui.AbstractField.setPropertyDataSource(AbstractField.java:657) ~[vaadin-server-7.6.8.jar:7.6.8]
    ... 48 common frames omitted

所以看起来为列定义的转换器不会在编辑器生成的字段中继承(正如人们可能预期的那样......也许?!)。

尽管如此,如果您手动定义编辑器字段并为其分配相同的转换器,那么它应该按预期工作。下面的完整示例,包括转换器中的次要更新以支持默认空值:

import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.data.util.converter.Converter;
import com.vaadin.ui.Grid;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class GridWithLocalTimeField extends VerticalLayout {
    public GridWithLocalTimeField() {
        // basic grid setup, double click row to edit
        BeanItemContainer<MyBean> container = new BeanItemContainer<>(MyBean.class);
        Grid grid = new Grid();
        grid.setContainerDataSource(container);
        grid.setEditorEnabled(true);
        grid.setSelectionMode(Grid.SelectionMode.SINGLE);
        addComponent(grid);

        // add a custom field for editing the LocalTime field
        TextField dateFieldEditor = new TextField();
        dateFieldEditor.setConverter(new StringToLocalTimeConverter());

        // configure grid column for the LocalTime field
        grid.getColumn("time")
                .setMinimumWidth(100)
                .setConverter(new StringToLocalTimeConverter())
                .setResizable(false)
                .setEditorField(dateFieldEditor); // comment this to get the stacktrace

        // add some dummy data
        for (int i = 0; i < 10; i++) {
            container.addBean(new MyBean(LocalTime.now(), i));
        }
    }

    public static class StringToLocalTimeConverter implements Converter<String, LocalTime> {
        public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm");

        @Override
        public LocalTime convertToModel(String value, Class<? extends LocalTime> targetType, Locale locale) throws ConversionException {
            if (value == null || value.isEmpty()) {
                return null;
            } else {
                return LocalTime.parse(value, TIME_FORMATTER);
            }
        }

        @Override
        public String convertToPresentation(LocalTime value, Class<? extends String> targetType, Locale locale) throws ConversionException {
            if (value == null) {
                return "";
            } else {
                return value.format(TIME_FORMATTER);
            }
        }

        @Override
        public Class<LocalTime> getModelType() {
            return LocalTime.class;
        }

        @Override
        public Class<String> getPresentationType() {
            return String.class;
        }
    }

    public static class MyBean {
        private LocalTime time;
        private int order;

        public MyBean(LocalTime time, int order) {
            this.time = time;
            this.order = order;
        }

        public LocalTime getTime() {
            return time;
        }

        public void setTime(LocalTime time) {
            this.time = time;
        }

        public int getOrder() {
            return order;
        }

        public void setOrder(int order) {
            this.order = order;
        }
    }
}

结果:

Grid with LocalTime fields