Vaadinテキストフィールドを使用していますが、その中の数字のみをサポートするように制限したいと思います。 setValue()
をオーバーライドして、superを呼び出さずに戻ろうとしました。 setValue()
テキストが数字でない場合。しかし、それは機能していないようです。どうすればこれを修正できますか? Vaadin 7を使用していますが、NumberFieldもサポートしていないと思います。
質問が正しいと理解した場合は、数値ではないすべての入力を無視し、フィールドを無効としてマークするだけではないフィールドが必要です。 Vaadinsアーキテクチャは、ブラウザのすべてのフィールドがサーバー上でその表現を持つように設計されています。私の意見では、これを達成するための最もクリーンな方法は、文字やその他の間違った文字の入力を許可するブラウザフィールドを持つことです。 Vaadin 7でそのようなフィールドを見つけることができませんでした。そのための Number Field というvaadin 6のアドオンがあるようですが、テストしませんでした。
複数のオプションがあります:
このアドオンをvaadin7に移植するか、作成者に依頼してください
独自のフィールドを作成します。たぶんVTextFieldとTextFieldConnectorを拡張する
サーバー側ですべてを実行し、遅延とトラフィックを受け入れます(IMHO醜い)
オプション3はnotの方法だと思うので、おそらくこのコードを表示するべきではありませんが、これを実装する最も簡単な方法です。
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では、組み込みのウィジェットを拡張できます(これについてさらに知識が必要な場合は、これをお勧めします post )ここにそのメカニズムを使用するソリューションがあります。
これは、コネクタと拡張機能の2つのクラスで構成されています。
拡張機能
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);
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);
}
}
TextField
は、常にタイプString
の値を持つコンポーネントです。別のタイプのプロパティをテキストフィールドにバインドする場合、2つのタイプ間の変換がサポートされていれば、値は自動的に変換されます。
public class MyBean {
private int value;
public int getValue() {
return value;
}
public void setValue(int integer) {
value = integer;
}
}
BeanItem
から構築されたMyBean
の "value"という名前のプロパティは、タイプ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になります。例:フィールドに文字を入力してボタンを押すと、検証は失敗します。これにより、フィールドに通知が表示されます。フィールド値は引き続き更新されますが、プロパティ値とBean値は以前の値のままになります。
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 は、Vaadin7および8で使用できるようになりました。