用于整数输入的JavaFX TextField验证,并允许最后使用K或k(对于千)或M或m(对于百万) [英] JavaFX TextField validation for integer input and also allow either K or k(for Thousand) or M or m(for Million) in last

查看:117
本文介绍了用于整数输入的JavaFX TextField验证,并允许最后使用K或k(对于千)或M或m(对于百万)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在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(对于百万)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆