问题描述
我想在javafx TextField中添加验证,以便用户只能插入整数值([0-9]和Dot)。用户也应该能够插入B或b(对于Billion)和K或k(对于千)和M或m(对于百万)。基本上它应该是一个数量字段。删除和退格也应该有效。
I want to add validation in javafx TextField such that user should only be able to insert integer values ([0-9] and Dot ). Also user should be able to insert either B or b(for Billion) and K or k (for Thousand) and M or m( for Million). Basically it should be an amountfield. Delete and Backspace should also work.
例如:
一旦用户点击k,10k应该变为10,000.00和K不应显示在金额字段(文本字段)
同样10M或10m应转换为10,000,000.00
10k should become 10,000.00 as soon as user hit k and K should not be displayed on amountfield (textfield)Similarly 10M or 10m should convert into 10,000,000.00
不允许adadi342fn3或31233123werwer或dsad342134k进入textfield。
adsadi342fn3 or 31233123werwer or dsad342134k should not be allowed to enter in the textfield.
我在使用Swing时验证TextField时使用了getKeyChar方法。但是我在JavaFx的情况下需要相同的实现,我们没有getKeyChar方法。
I have used getKeyChar method while validating TextField in case of Swing. But I need same implementation in case of JavaFx where we don't have getKeyChar method.
我使用了以下方法,但问题是它允许用户输入任何价值。示例:sdafewr23rf
I have used the following method but the problem with this is it allows user to enter any value. example : sdafewr23rf
private void amountEntered() {
if (amountField != null) {
String value;
char[] charArray = amountField.getText().toCharArray();
if (charArray.length > 0)
switch (charArray[charArray.length - 1]) {
case 't':
case 'T':
value = multiplyValue(amountField.getText(), new BigDecimal(1000000000000.0));
updateAmount(value);
break;
case 'b':
case 'B':
value = multiplyValue(amountField.getText(), new BigDecimal(1000000000.0));
updateAmount(value);
break;
case 'm':
case 'M':
value = multiplyValue(amountField.getText(), new BigDecimal(1000000.0));
updateAmount(value);
break;
case 'k':
case 'K':
value = multiplyValue(amountField.getText(), new BigDecimal(1000.0));
updateAmount(value);
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
case ',':
updateAmount(amountField.getText());
break;
default:
break;
}
}
}
private String multiplyValue(String number, BigDecimal multValue) {
//get rid of "," for double parsing
BigDecimal value = new BigDecimal(cleanDouble(number.substring(0, number.length() - 1)));
value = value.multiply(multValue);
return value.toPlainString();
}
推荐答案
我创建了以下类来在 TextField
上过滤输入,它还使用JavaFX 8中引入的 TextFormatter
。
I created the following class to filter input on TextField
, which also uses the TextFormatter
introduced in JavaFX 8.
public class TextFieldValidator {
private static final String CURRENCY_SYMBOL = DecimalFormatSymbols.getInstance().getCurrencySymbol();
private static final char DECIMAL_SEPARATOR = DecimalFormatSymbols.getInstance().getDecimalSeparator();
private final Pattern INPUT_PATTERN;
public TextFieldValidator(@NamedArg("modus") ValidationModus modus, @NamedArg("maxCountOf") int maxCountOf) {
this(modus.createPattern(maxCountOf));
}
public TextFieldValidator(@NamedArg("regex") String regex){
this(Pattern.compile(regex));
}
public TextFieldValidator(Pattern pattern){
INPUT_PATTERN = pattern;
}
public static TextFieldValidator maxFractionDigits(int maxCountOf) {
return new TextFieldValidator(maxFractionPattern(maxCountOf));
}
public static TextFieldValidator maxIntegers(int maxCountOf) {
return new TextFieldValidator(maxIntegerPattern(maxCountOf));
}
public static TextFieldValidator integersOnly() {
return new TextFieldValidator(integersOnlyPattern());
}
public TextFormatter<Object> getFormatter() {
return new TextFormatter<>(this::validateChange);
}
private Change validateChange(Change c) {
if (validate(c.getControlNewText())) {
return c;
}
return null;
}
public boolean validate(String input) {
return INPUT_PATTERN.matcher(input).matches();
}
private static Pattern maxFractionPattern(int maxCountOf) {
return Pattern.compile("\\d*(\\" + DECIMAL_SEPARATOR + "\\d{0," + maxCountOf+ "})?");
}
private static Pattern maxCurrencyFractionPattern(int maxCountOf) {
return Pattern.compile("^\\" + CURRENCY_SYMBOL + "?\\s?\\d*(\\" + DECIMAL_SEPARATOR + "\\d{0," + maxCountOf+ "})?\\s?\\" +
CURRENCY_SYMBOL + "?");
}
private static Pattern maxIntegerPattern(int maxCountOf) {
return Pattern.compile("\\d{0," + maxCountOf+ "}");
}
private static Pattern integersOnlyPattern() {
return Pattern.compile("\\d*");
}
public enum ValidationModus {
MAX_CURRENCY_FRACTION_DIGITS {
@Override
public Pattern createPattern(int maxCountOf) {
return maxCurrencyFractionPattern(maxCountOf);
}
},
MAX_FRACTION_DIGITS {
@Override
public Pattern createPattern(int maxCountOf) {
return maxFractionPattern(maxCountOf);
}
},
MAX_INTEGERS {
@Override
public Pattern createPattern(int maxCountOf) {
return maxIntegerPattern(maxCountOf);
}
},
INTEGERS_ONLY {
@Override
public Pattern createPattern(int maxCountOf) {
return integersOnlyPattern();
}
};
public abstract Pattern createPattern(int maxCountOf);
}
}
您可以像这样使用它:
textField.setTextFormatter(new TextFieldValidator(ValidationModus.MAX_INTEGERS, 4).getFormatter());
或者您可以在fxml文件中实例化它,并将其应用于具有相应属性的customTextField。
or you can instantiate it in a fxml file, and apply it to a customTextField with the according properties.
app.fxml:
<fx:define>
<TextFieldValidator fx:id="validator" modus="MAX_INTEGERS" maxCountOf="4"/>
</fx:define>
<CustomTextField validator="$validator" />
CustomTextField:
CustomTextField:
public class CustomTextField {
private TextField textField;
public CustomTextField(@NamedArg("validator") TextFieldValidator validator) {
this();
textField.setTextFormatter(validator.getFormatter());
}
}
对于你的用例,你可以调用TextFieldValidor构造函数适当的正则表达式模式,并将James-D的答案过滤器添加到 validateChange(更改c)
For your usecase you could call the TextFieldValidor constructor with the appropriate regex pattern and add the filter of James-D's answer to validateChange(Change c)
这篇关于用于整数输入的JavaFX TextField验证,并允许最后使用K或k(对于千)或M或m(对于百万)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!