как создать текстовое поле, которое поддерживает числа только в vaadin
Я использую текстовое поле Vaadin, и я хочу ограничить его только номерами поддержки. Я попытался переопределить setValue()
и вернуться без вызова супер. setValue()
Если текст не является числом. Но, кажется, это не работает. Как я могу это исправить?
Я использую Vaadin 7. И я думаю, что это не поддержка, а также номер.
7 ответов
если я правильно понял ваш вопрос, вы хотите иметь поле, которое игнорирует все входные данные, которые не являются числом, а не только помечает поле как недопустимое. Архитектура Vaadins разработана таким образом, что каждое поле в браузере имеет свое представление на сервере. На мой взгляд, самый чистый способ добиться этого-иметь поле браузера, которое позволяет вводить буквы и другие неправильные символы. Я не могу найти такого поля в фреймворк Vaadin 7. Там похоже на фреймворк Vaadin 6 называется Поле для этого, но я не протестировать его.
У вас есть несколько вариантов:
перенесите это дополнение на vaadin 7 или попросите автора сделать это
напишите свое собственное поле. Возможно, расширение VTextField и TextFieldConnector
сделайте все на стороне сервера и примите задержки и трафик (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 позволяет расширить их встроенные виджеты (если вы хотите иметь больше знаний об этом, я действительно рекомендую это в должности) вот решение, которое использует этот механизм.
Он состоит из двух классов: Разъем и расширение
-
Расширение
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);
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