Как создать текстовое поле, которое поддерживает числа только в ваадине
Я использую текстовое поле Vaadin, и я хочу ограничить его поддержкой номеров только в нем. Я попытался переопределить setValue()
и вернуться без вызова super. setValue()
если текст не является числом. Но, похоже, это не работает. Как я могу это исправить?
Я использую Vaadin 7. И я думаю, что он также не поддерживает NumberField.
Ответы
Ответ 1
Если я правильно понимаю ваш вопрос, вы хотите иметь поле, которое игнорирует все входы, которые не являются числом, и не только помечать поле как недопустимое. Архитектура Vaadins спроектирована так, что каждое поле в браузере имеет свое представление на сервере. На мой взгляд, самым чистым способом добиться этого было бы иметь поле браузера, позволяющее вводить буквы и другие неправильные символы. Я не мог найти такое поле в Vaadin 7. Для него, похоже, добавлено дополнение для vaadin 6 под названием Number Field, но я его не тестировал,
У вас есть несколько вариантов:
-
Добавьте это дополнение к vaadin 7 или попросите автора сделать это
-
Напишите свое собственное поле. Возможно расширение VTextField и TextFieldConnector
-
Сделайте все на стороне сервера и примите задержки и трафик (IMHO уродливый)
Так как я думаю, что вариант 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);
}
}
}
Ответ 2
Vaadin 7 позволяет расширить свои встроенные виджеты (если вы хотите получить больше знаний об этом, я действительно рекомендую этот пост), вот решение, которое использует этот механизм.
Он состоит из двух классов:
Коннектор и расширение
-
Расширение
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);
}
}
-
Разъем:
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);
Ответ 3
A TextField
- это компонент, который всегда имеет значение типа String
. При привязке свойства другого типа к текстовому полю значение автоматически преобразуется, если поддерживается преобразование между двумя типами.
public class MyBean {
private int value;
public int getValue() {
return value;
}
public void setValue(int integer) {
value = integer;
}
}
Свойство с именем "значение" из BeanItem
, построенное из MyBean
, будет иметь тип 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 сохраняются при их предыдущих значениях.
Ответ 4
В Vaadin 7 вы можете использовать TextField и установить валидатор, чтобы разрешить только числа:
TextField textField;
textField.addValidator(new RegexpValidator("[-]?[0-9]*\\.?,?[0-9]+"), "This is not a number!");
Измените регулярное выражение в соответствии с вашими потребностями.
Помните, что все еще обрабатывает строки и поэтому вам все равно нужно преобразовать возвращаемое значение TextField:
Long.parseLong(textField.getValue())
Ответ 5
Это обновление (2017 с vaadin 8) для ответа @raffael:
public class DoubleField extends TextField implements ValueChangeListener<String> {
/**
*
*/
private static final long serialVersionUID = 1L;
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);
}
}
Вуаля!
Ответ 6
NumberField теперь доступен для Vaadin 7 и 8.