GWT DatePickerCell 显示“空”日期?

发布于 2024-12-12 08:04:50 字数 660 浏览 0 评论 0原文

我正在使用带有 DatePickerCell 的 CellTable,并且我希望能够显示未设置的日期,例如“空”日期。但在实现 getValue 方法时,我必须返回一些内容:

        Column<EventProxy, Date> startTimeColumn = new Column<EventProxy, Date>(
            new DatePickerCell()) {
                @Override
                public Date getValue(EventProxy object) {
                    Date ret = object.getStartTime();
                    return ret != null ? ret : new Date();
                }
    };

如果 object.getStartTime() 为 null,则意味着它未设置,我想按原样显示它。或者使用空标签或文本“空”。正如我所说,方法 getValue 必须返回一些内容。如果我返回 null,稍后会出现异常,如果我返回具体日期,它会将其显示为有效日期。还有其他选择吗? DatePickerCell 会识别为空或未设置值的某些特殊日期标记或对象吗?

I am using a CellTable with also DatePickerCell and I'd like to be able to display also dates that are not set, e.g. "empty" date. But in implementing getValue method I have to return something:

        Column<EventProxy, Date> startTimeColumn = new Column<EventProxy, Date>(
            new DatePickerCell()) {
                @Override
                public Date getValue(EventProxy object) {
                    Date ret = object.getStartTime();
                    return ret != null ? ret : new Date();
                }
    };

If object.getStartTime() is null, it means that it is not set and I want to display it as such. Or with empty label or with text "empty". As I've said, method getValue has to return something. If I return null, I get exceptions later, if I return concrete date it displays it as valid date. Is there any other option? Some special date tag or object that DatePickerCell would recognize as empty or unset value?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

度的依靠╰つ 2024-12-19 08:04:50

您想知道如何显示日期,对吗?然后将焦点从 getValue() 上移开,并考虑重写 render() 方法(在 Column 类中找到)。 render() 方法有一个对象参数,就像 getValue() 一样,还有一个 SafeHtmlBuilder 的参数,您可以将对象值的表示形式附加到该参数。测试 getStartTime(),如果它为 null,则将“[unset]”(或其他内容)附加到该 SafeHtmlBuilder。您甚至可以附加一个带有红色删除线的钟面图像(使用 HTML img 标签),或者您关心的任何内容,因为渲染只是附加将放入单元格中的 HTML。

第 10 版中提供的新类与您没有直接关系,但在其他情况下可能对您有用。番石榴。它称为 可选。它是一个泛型,包含您正在使用的类,在本例中为 Date。它提供了一种使用提供的方法显式区分 null 值和未设置值等的方法。快速阅读一下 - 由于您正在处理空日期,因此这可能在您设计的其他地方很有用。

You are wondering about displaying dates, right? Then shift your focus away from getValue() and look at overriding the render() method (found in the Column class) instead. The render() method has an object parameter, just like getValue(), and a parameter for a SafeHtmlBuilder to which you append your representation of the object's value. Test getStartTime(), and if it is null, append "[unset]" (or whatever) to that SafeHtmlBuilder. You could even append an image of a clock face with a red strikeout running through it (using the HTML img tag), or anything you care to, since render is just appending HTML that will be put into the cell.

Not directly related, but perhaps useful in another context for you, is a new class delivered in Release 10 of Guava. It is called Optional. It is a generic that wraps around the class you're using, in this case, Date. It provides a way to explicitly distinguish between a null value, and unset value, and so on, using the methods provided. Give it a quick read -- since you are dealing with empty dates, this might be useful elsewhere in your design.

我早已燃尽 2024-12-19 08:04:50

DatePickerCell 不支持空值。重写 render 是不够的,因为当您单击呈现的单元格时,onEnterKeyDown 方法会抛出 NPE

您必须在“onEnterKeyDown”中实现带有空保护的自己的单元格:

if (date != null) {
    datePicker.setCurrentMonth(date);
}

完整类:

public class DatePickerCell extends AbstractEditableCell<Date, Date> {

private static final int ESCAPE = 27;

private final DatePicker datePicker;
private final DateTimeFormat format;
private int offsetX = 10;
private int offsetY = 10;
private Object lastKey;
private Element lastParent;
private int lastIndex;
private int lastColumn;
private Date lastValue;
private PopupPanel panel;
private final SafeHtmlRenderer<String> renderer;
private ValueUpdater<Date> valueUpdater;

/**
 * Constructs a new DatePickerCell that uses the date/time format given by
 * {@link DateTimeFormat#getFullDateFormat}.
 */
@SuppressWarnings("deprecation")
public DatePickerCell() {
    this(DateTimeFormat.getFullDateFormat(), SimpleSafeHtmlRenderer.getInstance());
}

/**
 * Constructs a new DatePickerCell that uses the given date/time format and
 * a {@link SimpleSafeHtmlRenderer}.
 * @param format a {@link DateTimeFormat} instance
 */
public DatePickerCell(DateTimeFormat format) {
    this(format, SimpleSafeHtmlRenderer.getInstance());
}

/**
 * Constructs a new DatePickerCell that uses the date/time format given by
 * {@link DateTimeFormat#getFullDateFormat} and the given
 * {@link SafeHtmlRenderer}.
 * @param renderer a {@link SafeHtmlRenderer SafeHtmlRenderer<String>}
 *            instance
 */
public DatePickerCell(SafeHtmlRenderer<String> renderer) {
    this(DateTimeFormat.getFormat(PredefinedFormat.DATE_FULL), renderer);
}

/**
 * Constructs a new DatePickerCell that uses the given date/time format and
 * {@link SafeHtmlRenderer}.
 * @param format a {@link DateTimeFormat} instance
 * @param renderer a {@link SafeHtmlRenderer SafeHtmlRenderer<String>}
 *            instance
 */
public DatePickerCell(DateTimeFormat format, SafeHtmlRenderer<String> renderer) {
    super(CLICK, KEYDOWN);
    if (format == null) {
        throw new IllegalArgumentException("format == null");
    }
    if (renderer == null) {
        throw new IllegalArgumentException("renderer == null");
    }
    this.format = format;
    this.renderer = renderer;

    this.datePicker = new DatePicker();
    this.panel = new PopupPanel(true, true) {
        @Override
        protected void onPreviewNativeEvent(NativePreviewEvent event) {
            if (Event.ONKEYUP == event.getTypeInt()) {
                if (event.getNativeEvent().getKeyCode() == ESCAPE) {
                    // Dismiss when escape is pressed
                    panel.hide();
                }
            }
        }
    };
    panel.addCloseHandler(new CloseHandler<PopupPanel>() {
        public void onClose(CloseEvent<PopupPanel> event) {
            lastKey = null;
            lastValue = null;
            lastIndex = -1;
            lastColumn = -1;
            if (lastParent != null && !event.isAutoClosed()) {
                // Refocus on the containing cell after the user selects a
                // value, but
                // not if the popup is auto closed.
                lastParent.focus();
            }
            lastParent = null;
        }
    });
    panel.add(datePicker);

    // Hide the panel and call valueUpdater.update when a date is selected
    datePicker.addValueChangeHandler(new ValueChangeHandler<Date>() {
        public void onValueChange(ValueChangeEvent<Date> event) {
            // Remember the values before hiding the popup.
            Element cellParent = lastParent;
            Date oldValue = lastValue;
            Object key = lastKey;
            int index = lastIndex;
            int column = lastColumn;
            panel.hide();

            // Update the cell and value updater.
            Date date = event.getValue();
            setViewData(key, date);
            setValue(new Context(index, column, key), cellParent, oldValue);
            if (valueUpdater != null) {
                valueUpdater.update(date);
            }
        }
    });
}

@Override
public boolean isEditing(Context context, Element parent, Date value) {
    return lastKey != null && lastKey.equals(context.getKey());
}

@Override
public void onBrowserEvent(Context context, Element parent, Date value, NativeEvent event, ValueUpdater<Date> valueUpdater) {
    super.onBrowserEvent(context, parent, value, event, valueUpdater);
    if (CLICK.equals(event.getType())) {
        onEnterKeyDown(context, parent, value, event, valueUpdater);
    }
}

@Override
public void render(Context context, Date value, SafeHtmlBuilder sb) {
    // Get the view data.
    Object key = context.getKey();
    Date viewData = getViewData(key);
    if (viewData != null && viewData.equals(value)) {
        clearViewData(key);
        viewData = null;
    }

    String s = null;
    if (viewData != null) {
        s = format.format(viewData);
    } else if (value != null) {
        s = format.format(value);
    }
    if (s != null) {
        sb.append(renderer.render(s));
    }
}

@Override
protected void onEnterKeyDown(Context context, Element parent, Date value, NativeEvent event, ValueUpdater<Date> valueUpdater) {
    this.lastKey = context.getKey();
    this.lastParent = parent;
    this.lastValue = value;
    this.lastIndex = context.getIndex();
    this.lastColumn = context.getColumn();
    this.valueUpdater = valueUpdater;

    Date viewData = getViewData(lastKey);
    Date date = (viewData == null) ? lastValue : viewData;
    if (date != null) {
        datePicker.setCurrentMonth(date);
    }
    datePicker.setValue(date);
    panel.setPopupPositionAndShow(new PositionCallback() {
        public void setPosition(int offsetWidth, int offsetHeight) {
            panel.setPopupPosition(lastParent.getAbsoluteLeft() + offsetX, lastParent.getAbsoluteTop() + offsetY);
        }
    });
}

}

DatePickerCell does not support null values. Overriding render is not enough as NPE is thrown from method onEnterKeyDown when you click on the rendered cell.

You have to implement your own cell with null protection in "onEnterKeyDown" :

if (date != null) {
    datePicker.setCurrentMonth(date);
}

Complete class :

public class DatePickerCell extends AbstractEditableCell<Date, Date> {

private static final int ESCAPE = 27;

private final DatePicker datePicker;
private final DateTimeFormat format;
private int offsetX = 10;
private int offsetY = 10;
private Object lastKey;
private Element lastParent;
private int lastIndex;
private int lastColumn;
private Date lastValue;
private PopupPanel panel;
private final SafeHtmlRenderer<String> renderer;
private ValueUpdater<Date> valueUpdater;

/**
 * Constructs a new DatePickerCell that uses the date/time format given by
 * {@link DateTimeFormat#getFullDateFormat}.
 */
@SuppressWarnings("deprecation")
public DatePickerCell() {
    this(DateTimeFormat.getFullDateFormat(), SimpleSafeHtmlRenderer.getInstance());
}

/**
 * Constructs a new DatePickerCell that uses the given date/time format and
 * a {@link SimpleSafeHtmlRenderer}.
 * @param format a {@link DateTimeFormat} instance
 */
public DatePickerCell(DateTimeFormat format) {
    this(format, SimpleSafeHtmlRenderer.getInstance());
}

/**
 * Constructs a new DatePickerCell that uses the date/time format given by
 * {@link DateTimeFormat#getFullDateFormat} and the given
 * {@link SafeHtmlRenderer}.
 * @param renderer a {@link SafeHtmlRenderer SafeHtmlRenderer<String>}
 *            instance
 */
public DatePickerCell(SafeHtmlRenderer<String> renderer) {
    this(DateTimeFormat.getFormat(PredefinedFormat.DATE_FULL), renderer);
}

/**
 * Constructs a new DatePickerCell that uses the given date/time format and
 * {@link SafeHtmlRenderer}.
 * @param format a {@link DateTimeFormat} instance
 * @param renderer a {@link SafeHtmlRenderer SafeHtmlRenderer<String>}
 *            instance
 */
public DatePickerCell(DateTimeFormat format, SafeHtmlRenderer<String> renderer) {
    super(CLICK, KEYDOWN);
    if (format == null) {
        throw new IllegalArgumentException("format == null");
    }
    if (renderer == null) {
        throw new IllegalArgumentException("renderer == null");
    }
    this.format = format;
    this.renderer = renderer;

    this.datePicker = new DatePicker();
    this.panel = new PopupPanel(true, true) {
        @Override
        protected void onPreviewNativeEvent(NativePreviewEvent event) {
            if (Event.ONKEYUP == event.getTypeInt()) {
                if (event.getNativeEvent().getKeyCode() == ESCAPE) {
                    // Dismiss when escape is pressed
                    panel.hide();
                }
            }
        }
    };
    panel.addCloseHandler(new CloseHandler<PopupPanel>() {
        public void onClose(CloseEvent<PopupPanel> event) {
            lastKey = null;
            lastValue = null;
            lastIndex = -1;
            lastColumn = -1;
            if (lastParent != null && !event.isAutoClosed()) {
                // Refocus on the containing cell after the user selects a
                // value, but
                // not if the popup is auto closed.
                lastParent.focus();
            }
            lastParent = null;
        }
    });
    panel.add(datePicker);

    // Hide the panel and call valueUpdater.update when a date is selected
    datePicker.addValueChangeHandler(new ValueChangeHandler<Date>() {
        public void onValueChange(ValueChangeEvent<Date> event) {
            // Remember the values before hiding the popup.
            Element cellParent = lastParent;
            Date oldValue = lastValue;
            Object key = lastKey;
            int index = lastIndex;
            int column = lastColumn;
            panel.hide();

            // Update the cell and value updater.
            Date date = event.getValue();
            setViewData(key, date);
            setValue(new Context(index, column, key), cellParent, oldValue);
            if (valueUpdater != null) {
                valueUpdater.update(date);
            }
        }
    });
}

@Override
public boolean isEditing(Context context, Element parent, Date value) {
    return lastKey != null && lastKey.equals(context.getKey());
}

@Override
public void onBrowserEvent(Context context, Element parent, Date value, NativeEvent event, ValueUpdater<Date> valueUpdater) {
    super.onBrowserEvent(context, parent, value, event, valueUpdater);
    if (CLICK.equals(event.getType())) {
        onEnterKeyDown(context, parent, value, event, valueUpdater);
    }
}

@Override
public void render(Context context, Date value, SafeHtmlBuilder sb) {
    // Get the view data.
    Object key = context.getKey();
    Date viewData = getViewData(key);
    if (viewData != null && viewData.equals(value)) {
        clearViewData(key);
        viewData = null;
    }

    String s = null;
    if (viewData != null) {
        s = format.format(viewData);
    } else if (value != null) {
        s = format.format(value);
    }
    if (s != null) {
        sb.append(renderer.render(s));
    }
}

@Override
protected void onEnterKeyDown(Context context, Element parent, Date value, NativeEvent event, ValueUpdater<Date> valueUpdater) {
    this.lastKey = context.getKey();
    this.lastParent = parent;
    this.lastValue = value;
    this.lastIndex = context.getIndex();
    this.lastColumn = context.getColumn();
    this.valueUpdater = valueUpdater;

    Date viewData = getViewData(lastKey);
    Date date = (viewData == null) ? lastValue : viewData;
    if (date != null) {
        datePicker.setCurrentMonth(date);
    }
    datePicker.setValue(date);
    panel.setPopupPositionAndShow(new PositionCallback() {
        public void setPosition(int offsetWidth, int offsetHeight) {
            panel.setPopupPosition(lastParent.getAbsoluteLeft() + offsetX, lastParent.getAbsoluteTop() + offsetY);
        }
    });
}

}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文