как создать текстовое поле, которое поддерживает числа только в vaadin

Я использую текстовое поле Vaadin, и я хочу ограничить его только номерами поддержки. Я попытался переопределить setValue() и вернуться без вызова супер. setValue() Если текст не является числом. Но, кажется, это не работает. Как я могу это исправить? Я использую Vaadin 7. И я думаю, что это не поддержка, а также номер.

7 ответов


если я правильно понял ваш вопрос, вы хотите иметь поле, которое игнорирует все входные данные, которые не являются числом, а не только помечает поле как недопустимое. Архитектура Vaadins разработана таким образом, что каждое поле в браузере имеет свое представление на сервере. На мой взгляд, самый чистый способ добиться этого-иметь поле браузера, которое позволяет вводить буквы и другие неправильные символы. Я не могу найти такого поля в фреймворк Vaadin 7. Там похоже на фреймворк Vaadin 6 называется Поле для этого, но я не протестировать его.
У вас есть несколько вариантов:

  1. перенесите это дополнение на vaadin 7 или попросите автора сделать это

  2. напишите свое собственное поле. Возможно, расширение VTextField и TextFieldConnector

  3. сделайте все на стороне сервера и примите задержки и трафик (IMHO ugly)

Так как я думаю, что Вариант 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 позволяет расширить их встроенные виджеты (если вы хотите иметь больше знаний об этом, я действительно рекомендую это в должности) вот решение, которое использует этот механизм.

Он состоит из двух классов: Разъем и расширение

  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);

A TextField - это компонент, который всегда имеет значение типа String. При привязке свойства другого типа к текстовому полю значение автоматически преобразуется, если поддерживается преобразование между двумя типами.

public class MyBean {
    private int value;

    public int getValue() {
        return value;
    }

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

свойство с именем "value" из BeanItem построены из MyBean будет типа Integer. Привязка свойства к TextField автоматически приведет к сбою проверки для текстов, которые не могут быть преобразованы в Целое число.

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. Если, например, в поле введена буква и нажата кнопка, проверка завершится ошибкой. Это приводит к отображению уведомления для поля. Значение поля по-прежнему обновляется, но значение свойства и значение компонента сохраняются на их прежние ценности.


в Vaadin 7 Вы можете использовать текстовое поле и установить валидатор, чтобы разрешить только числа:

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

измените регулярное выражение в соответствии с вашими потребностями. Помните, что все еще обрабатывает строки, и поэтому вам все равно нужно преобразовать возвращаемое значение TextField:

Long.parseLong(textField.getValue())

это обновление (2017 с vaadin 8) для @raffael ответ:

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

номер доступно для Vaadin 7 и 8 к настоящему времени.