JavaFX 8のTextFormatterを使用して、整数用の数値TextFieldを作成しようとしています。
naryOperatorによるソリューション:
UnaryOperator<Change> integerFilter = change -> {
String input = change.getText();
if (input.matches("[0-9]*")) {
return change;
}
return null;
};
myNumericField.setTextFormatter(new TextFormatter<String>(integerFilter));
IntegerStringConverterによるソリューション:
myNumericField.setTextFormatter(new TextFormatter<>(new IntegerStringConverter()));
どちらのソリューションにも独自の問題があります。 UnaryOperatorでは、意図したように0〜9の数字のみを入力できますが、「-512」のような負の値も入力する必要があります。また、「00016」のような数字は必要ありませんが、これはまだ可能です。
IntegerStringConverterメソッドの方がうまく機能します。「-16-123」などの無効な数値はすべて受け入れられず、「0123」などの数値は「123」に変換されます。ただし、変換は、テキストが(Enterキーを押して)コミットされるか、TextFieldがフォーカスを失ったときにのみ発生します。
TextFieldの値が更新されるたびに、IntegerStringConverterを使用して2番目のメソッドの変換を強制する方法はありますか?
コンバーターはフィルターとは異なります。コンバーターはテキストを値に変換する方法を指定し、フィルターはユーザーが行う変更をフィルターします。ここでは両方を必要としているように聞こえますが、許可された変更をより正確にフィルター処理する必要があります。
通常、変更が受け入れられた場合、テキストの新しい値を確認するのが最も簡単です。必要に応じて、-
、 に続く 1-9
の後に任意の桁数を付けます。空の文字列を許可することが重要です。そうしないと、ユーザーはすべてを削除できません。
したがって、おそらく次のようなものが必要です
UnaryOperator<Change> integerFilter = change -> {
String newText = change.getControlNewText();
if (newText.matches("-?([1-9][0-9]*)?")) {
return change;
}
return null;
};
myNumericField.setTextFormatter(
new TextFormatter<Integer>(new IntegerStringConverter(), 0, integerFilter));
フィルタにさらに機能を追加して、_-
よりスマートな方法で、例えば.
UnaryOperator<Change> integerFilter = change -> {
String newText = change.getControlNewText();
// if proposed change results in a valid value, return change as-is:
if (newText.matches("-?([1-9][0-9]*)?")) {
return change;
} else if ("-".equals(change.getText()) ) {
// if user types or pastes a "-" in middle of current text,
// toggle sign of value:
if (change.getControlText().startsWith("-")) {
// if we currently start with a "-", remove first character:
change.setText("");
change.setRange(0, 1);
// since we're deleting a character instead of adding one,
// the caret position needs to move back one, instead of
// moving forward one, so we modify the proposed change to
// move the caret two places earlier than the proposed change:
change.setCaretPosition(change.getCaretPosition()-2);
change.setAnchor(change.getAnchor()-2);
} else {
// otherwise just insert at the beginning of the text:
change.setRange(0, 0);
}
return change ;
}
// invalid change, veto it by returning null:
return null;
};
これにより、ユーザーは-
任意の時点で、整数の符号を切り替えます。
SSCCE:
import Java.util.function.UnaryOperator;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.control.TextFormatter.Change;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.StringConverter;
import javafx.util.converter.IntegerStringConverter;
public class IntegerFieldExample extends Application {
@Override
public void start(Stage primaryStage) {
TextField integerField = new TextField();
UnaryOperator<Change> integerFilter = change -> {
String newText = change.getControlNewText();
if (newText.matches("-?([1-9][0-9]*)?")) {
return change;
} else if ("-".equals(change.getText()) ) {
if (change.getControlText().startsWith("-")) {
change.setText("");
change.setRange(0, 1);
change.setCaretPosition(change.getCaretPosition()-2);
change.setAnchor(change.getAnchor()-2);
return change ;
} else {
change.setRange(0, 0);
return change ;
}
}
return null;
};
// modified version of standard converter that evaluates an empty string
// as zero instead of null:
StringConverter<Integer> converter = new IntegerStringConverter() {
@Override
public Integer fromString(String s) {
if (s.isEmpty()) return 0 ;
return super.fromString(s);
}
};
TextFormatter<Integer> textFormatter =
new TextFormatter<Integer>(converter, 0, integerFilter);
integerField.setTextFormatter(textFormatter);
// demo listener:
textFormatter.valueProperty().addListener((obs, oldValue, newValue) -> System.out.println(newValue));
VBox root = new VBox(5, integerField, new Button("Click Me"));
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 300, 120);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
TextField txtpoint = new TextField();
txtpoint.textProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
if (!newValue.isEmpty()) {
try {
long pointI = Integer.parseInt(newValue);
txtpoint.setText(String.valueOf(pointI));
} catch (Exception e) {
txtpoint.clear();
txtpoint.setText(getNumber(oldValue));
}
}
}
});
private String getNumber(String value) {
String n = "";
try {
return String.valueOf(Integer.parseInt(value));
} catch (Exception e) {
String[] array = value.split("");
for (String tab : array) {
try {
System.out.println(tab);
n = n.concat(String.valueOf(Integer.parseInt(String.valueOf(tab))));
} catch (Exception ex) {
System.out.println("not nomber");
}
}
return n;
}
}