繁体   English   中英

如何创建仅在vaadin中支持数字的文本字段

[英]how do I create a textfield which supports numbers only in vaadin

我正在使用Vaadin文本字段,我想限制它仅支持数字。 我试图覆盖setValue()并返回而不调用super。 setValue()如果text不是数字。 但它似乎没有起作用。 我怎么能纠正这个? 我正在使用Vaadin 7.我认为它也不支持NumberField。

如果我理解你的问题是正确的,你想要一个忽略所有非数字输入的字段,而不仅仅是将该字段标记为无效。 Vaadins体系结构的设计是浏览器中的每个字段都在服务器上表示。 在我看来,实现这一目标的最简洁方法是拥有一个允许输入字母和其他错误字符的浏览器字段。 我在Vaadin 7中找不到这样的字段。似乎有一个名为Number Field的 vaadin 6的附加组件,但我没有测试它。
您有多种选择:

  1. 将此附加组件移植到vaadin 7或要求作者执行此操作

  2. 写你自己的领域。 也许扩展VTextField和TextFieldConnector

  3. 在服务器端执行所有操作并接受延迟和流量(恕我直言)

因为我认为选项3 不是要走的路,所以我可能不应该显示这段代码,但这是实现它的最快方法。

public class IntegerField extends TextField implements TextChangeListener {
String lastValue;

public IntegerField() {
    setImmediate(true);
    setTextChangeEventMode(TextChangeEventMode.EAGER);
    addTextChangeListener(this);
}

@Override
public void textChange(TextChangeEvent event) {
    String text = event.getText();
    try {
        new Integer(text);
        lastValue = text;
    } catch (NumberFormatException e) {
        setValue(lastValue);
    }
}
}

Vaadin 7允许扩展他们内置的小部件(如果你想对此有更多的了解我真的推荐这篇文章 )这里是一个使用该机制的解决方案。

它由两个类组成:Connector和Extension

  1. 扩展

     package com.infosystem.widgets.vaadin; import com.vaadin.server.AbstractClientConnector; import com.vaadin.server.AbstractExtension; import com.vaadin.ui.TextField; public class NumberField extends AbstractExtension { public static void extend(TextField field) { new NumberField().extend((AbstractClientConnector) field); } } 
  2. 连接器:

     package com.infosystem.widgets.vaadin.client.numberField; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyPressEvent; import com.google.gwt.event.dom.client.KeyPressHandler; import com.infosystem.widgets.vaadin.NumberField; import com.vaadin.client.ComponentConnector; import com.vaadin.client.ServerConnector; import com.vaadin.client.extensions.AbstractExtensionConnector; import com.vaadin.client.ui.VTextField; import com.vaadin.shared.ui.Connect; @Connect(NumberField.class) public class NumberFieldConnector extends AbstractExtensionConnector { private static final long serialVersionUID = -737765038361894693L; private VTextField textField; private KeyPressHandler keyPressHandler = new KeyPressHandler() { @Override public void onKeyPress(KeyPressEvent event) { if (textField.isReadOnly() || !textField.isEnabled()) { return; } int keyCode = event.getNativeEvent().getKeyCode(); switch (keyCode) { case KeyCodes.KEY_LEFT: case KeyCodes.KEY_RIGHT: case KeyCodes.KEY_BACKSPACE: case KeyCodes.KEY_DELETE: case KeyCodes.KEY_TAB: case KeyCodes.KEY_UP: case KeyCodes.KEY_DOWN: case KeyCodes.KEY_SHIFT: return; } if (!isValueValid(event)) { textField.cancelKey(); } } }; @Override protected void extend(ServerConnector target) { textField = (VTextField) ((ComponentConnector) target).getWidget(); textField.addKeyPressHandler(keyPressHandler); } private boolean isValueValid(KeyPressEvent event) { String newText = getFieldValueAsItWouldBeAfterKeyPress(event.getCharCode()); try { parseValue(newText); return true; } catch (Exception e) { return false; } } protected long parseValue(String value) { return Long.valueOf(value); } private String getFieldValueAsItWouldBeAfterKeyPress(char charCode) { int index = textField.getCursorPos(); String previousText = textField.getText(); StringBuffer buffer = new StringBuffer(); buffer.append(previousText.substring(0, index)); buffer.append(charCode); if (textField.getSelectionLength() > 0) { buffer.append(previousText.substring(index + textField.getSelectionLength(), previousText.length())); } else { buffer.append(previousText.substring(index, previousText.length())); } return buffer.toString(); } } 

要使用上面的代码,您需要将其添加到当前的窗口小部件集。 之后使用如下:

TextField field = new TextField();
NumberField.extend(field);

TextField是一个始终具有String类型值的组件。 将另一种类型的属性绑定到文本字段时,如果支持两种类型之间的转换,则会自动转换该值。

public class MyBean {
    private int value;

    public int getValue() {
        return value;
    }

    public void setValue(int integer) {
        value = integer;
    }
}

MyBean构造的BeanItem名为“value”的属性将为Integer类型。 将属性绑定到TextField将自动使无法转换为Integer的文本的验证失败。

final MyBean myBean = new MyBean();

BeanItem<MyBean> beanItem = new BeanItem<MyBean>(myBean);

final Property<Integer> integerProperty = (Property<Integer>) beanItem
        .getItemProperty("value");
final TextField textField = new TextField("Text field", integerProperty);

Button submitButton = new Button("Submit value", new ClickListener() {
    public void buttonClick(ClickEvent event) {
        String uiValue = textField.getValue();
        Integer propertyValue = integerProperty.getValue();
        int dataModelValue = myBean.getValue();

        Notification.show("UI value (String): " + uiValue
                + "\nProperty value (Integer): " + propertyValue
                + "\nData model value (int): " + dataModelValue);
     }
});

addComponent(new Label("Text field type: " + textField.getType()));
addComponent(new Label("Text field type: " + integerProperty.getType()));
addComponent(textField);
addComponent(submitButton);

在这个例子中,输入一个数字并按下按钮会使TextField的值为String ,属性值将是一个表示相同值的Integer ,并且bean中的值将是相同的int。 如果例如在字段中输入字母并按下按钮,则验证将失败。 这会导致显示该字段的通知。 字段值仍然更新,但属性值和bean值保持其先前的值。

在Vaadin 7中,您可以使用TextField并设置验证器以仅允许数字:

TextField textField;
textField.addValidator(new RegexpValidator("[-]?[0-9]*\\.?,?[0-9]+"), "This is not a number!");

更改正则表达式以满足您的需求。 请记住,仍然在处理字符串,因此您仍需要转换TextField的返回值:

Long.parseLong(textField.getValue())

这是@raffael回复的更新(2017年与vaadin 8):

public class DoubleField extends TextField implements ValueChangeListener<String>  {

public String lastValue;

public DoubleField() {
    setValueChangeMode(ValueChangeMode.EAGER);
    addValueChangeListener(this);
    lastValue="";
}

@Override
public void valueChange(ValueChangeEvent<String> event) {
    String text = (String) event.getValue();
    try {
        new Double(text);
        lastValue = text;
    } catch (NumberFormatException e) {
        setValue(lastValue);
    }

}

使用Vaadin 8,您可以使用Binder

Binder<YouBean> binder = new Binder<>();
binder.forField(textField)
      .withConverter(new StringToIntegerConverter("Must be Integer"))
      .bind(YouBean::getter, YouBean::setter);
binder.setBean(bean);  //optional

NumberField现在可用于Vaadin 7和8。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM