【问题标题】:GWT TextBox, DateBox, and such doesn't share same base input-classGWT TextBox、DateBox 等不共享相同的基本输入类
【发布时间】:2016-05-23 18:49:05
【问题描述】:

我目前正在处理一个现有的 GWT 项目。在这个项目中,我在视图上添加了一个列表,看起来像这样:

  • 标签 1:[文本框]
  • 标签2:[日期框]
  • 标签 3:[文本框]
  • 标签 4:[文本框]
  • 标签 5:[日期框]
  • 标签 6:[文本框]

我制作了一个从 FlowPanel 派生的小部件,我在其中创建了这些 Label-InputBox 对:

import java.sql.Date;

import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.datepicker.client.DateBox;

public class LabelInputWidget extends FlowPanel {

  private final Label      label;
  private final Widget     inputField;

  private static final int LABEL_AND_INPUTFIELD_WIDTH = 200;

  public LabelInputWidget(final String labelText, final Widget inputField) {
    super();

    this.label = new Label(labelText);
    this.label.getElement().getStyle().setDisplay(Display.INLINE_BLOCK); // Used to put the inputfield next to the label, instead of below it
    this.label.setWidth(LABEL_AND_INPUTFIELD_WIDTH + "px");
    this.add(this.label);

    this.inputField = inputField;
    // The DateBox width looks smaller when the same width is set, so we'll add 4 pixels to line it up with the other Input-Widgets
    int inputWidth = LABEL_AND_INPUTFIELD_WIDTH;
    if (inputField instanceof DateBox) {
      inputWidth += 4;
    }
    this.inputField.setWidth(inputWidth + "px");
    this.add(this.inputField);
  }

  // TODO KC: Use a less ugly way of determine which InputField is used
  // POTENTIAL TODO KC: Use custom widgets for Numeric / Currency input fields
  public void setInputValue(final String value) {
    if (this.inputField instanceof TextBox) {
      ((TextBox) this.inputField).setValue(value);
    } else if (this.inputField instanceof DateBox) {
      ((DateBox) this.inputField).setValue(value != null && value.length() > 0 ? Date.valueOf(value) : null);
    }
  }
}

在我创建这些字段的文件中,我有以下内容:

private void fillEditedProperties(final List<Property> list) {
  for (final Property p : list) {
    if (!containsProperty(p)) {
      this.editedProperties.add(p);

      // The moment the property is loaded and known, we add it to the view
      Widget inputWidget = new TextBox();
      if (Type.DATUM.name().equals(p.getPdf().getType().name())) {
        final DateBox dateBox = new DateBox();
        dateBox.setFormat(new DateBox.DefaultFormat(DateTimeFormat.getFormat("dd-MM-yyyy")));
        inputWidget = new DateBox();
      }
      final LabelInputWidget labelInput = new LabelInputWidget(p.getPdf().getName(), inputWidget);
      labelInput.setInputValue(p.getValue());
      labelInput.getElement().getStyle().setDisplay(Display.BLOCK); // Used to put the LabelInputWidgets below each other
      this.labelInputFieldsContainer.add(labelInput);
    }
  }
}

而且我还想在用户输入内容时验证输入(待办事项/正在进行的工作)。

正如您所见,将常规com.google.gwt.user.client.ui.Widget 用作TextBox 和DateBox 的共享基类非常难看。因为它们不共享诸如 InputBox 类之类的东西,所以我必须在确定使用哪个 (Input)Widget 之后设置它们的值,并且可能对 ValueChangedHandlers 执行相同的操作以验证我正要创建的用户输入。

有没有人知道在LabelInputWidgets 的同一个列表中同时使用 TextBoxes 和 DateBoxes 的更好解决方案,而不是几乎在所有地方都使用丑陋的 instanceof,而只需使用一种通用方法?

如果不是,我可能会在某处隐藏此行为,以使代码更具可读性..

PS:我不能 100% 确定这是 StackOverflow 的合适问题,所以我也在 CodeReview.StackExchange.com 上提出了一个交叉问题。我也在这里发布了它,但有两个原因:

  • 可能有人以完全不同的方式为此提供了合适的解决方案。
  • 这里的社区更大,所以我可能会更快得到答案..

【问题讨论】:

  • 好吧,您可以将 LabelInputWidget 抽象化,并通过重载方法对其进行两种实现(基于日期的一种和基于文本框的一种)
  • @РоманГуйван 我很愚蠢,呵呵.. 幸运的是快到周末了.. 感谢这个明显的解决方案。如果你愿意,你可以回答,我可以接受。 (不敢相信我什至想不出这么简单的事情..)。无论如何,谢谢,将立即开始。代码当然需要大量的重构和同事的审查。
  • @Kevin - 您可以使用 InlineLabel 代替 Label。
  • labelInput.getElement().getStyle().setDisplay(Display.BLOCK); 是不必要的。 FlowPanel 呈现为div
  • 好的,我已经找到答案了

标签: java generics gwt input parent-child


【解决方案1】:

你可以使用

public class LabelInputWidget<T> extends FlowPanel {

    private final Label         label;
    private final HasValue<T>   inputField;

...

其中&lt;T&gt; 可以是字符串或日期。

【讨论】:

  • HasValue&lt;T&gt; 实现似乎确实是两者之间的一个很好的共享类。我将结合使用您和 Роман Гуйван 的解决方案。
【解决方案2】:

您可以将 LabelInputWidget 抽象化,并有两个实现(基于日期的一个和基于文本框的一个),方法重载。

【讨论】:

    猜你喜欢
    • 2010-12-14
    • 1970-01-01
    • 1970-01-01
    • 2014-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-14
    • 2012-10-15
    相关资源
    最近更新 更多