【问题标题】:How to create a numeric localized (decimal separator) TextField?如何创建数字本地化(小数分隔符)TextField?
【发布时间】:2014-09-15 15:33:18
【问题描述】:

我想创建一个数字文本字段,它将被本地化。

例如,在 Excel 中,如果您使用英文,如果您使用 KeyPad 键入数字,则小数分隔键将输入一个点 '.' 但如果你是法语,小数点分隔符将是逗号','

因此,在 Excel 中,TextField 足够智能,可以检测您所在的区域设置,并调整您实际希望在 TextField 中打印的小数分隔符。

目前在 JavaFX 中,我还没有找到一种方法来做到这一点。如果我检测到我是法语,我正在考虑听文本修改并用逗号替换任何出现的点。但这个假设是真的吗?

【问题讨论】:

    标签: javafx javafx-8


    【解决方案1】:

    我建议继承 TextField 并覆盖 insertText 和 replace* 方法。这将在文本更新之前处理文本输入;监听文本修改并修复它们意味着您的文本字段的文本属性中暂时存在“无效”文本,这可能会在您的应用程序的其余部分中产生问题。

    请注意,您可以为默认(用户)Locale(或指定的Locale,如果需要)创建一个java.text.DecimalFormatSymbols 对象,并调用getDecimalSeparator() 以查找正确的小数分隔符。 (同样可以拨打getGroupingSeparator()。)

    因此,对于概念验证,这远不足以用于生产:

    public class NumericTextField extends TextField {
        @Override
        public void insertText(int index, String text) {
            String fixedText = fixText(text);
            StringBuilder newText = new StringBuilder(getText().substring(0, index));
            newText.append(fixedText);
            if (index < getText().length()) {
                newText.append(getText().substring(index));
            }
            if (isValid(newText)) {
                super.insertText(index, fixedText);
            }
        }
    
        @Override 
        public void replaceText(int start, int end, String text) {
            String fixedText = fixText(text);
            StringBuilder newText = new StringBuilder(getText().substring(0, start));
            newText.append(fixedText);
            newText.append(getText().substring(end));
            if (isValid(newText)) {
                super.insertText(start, end, fixedText);
            }
        }
    
        @Override
        public void replaceText(IndexRange range, String text) {
            replaceText(range.getStart(), range.getEnd(), text);
        }
    
    
        private String fixText(String text) {
            DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
            return text.replaceAll("\\.", Character.toString(symbols.getDecimalSeparator()));
        }
    
        private boolean isValid(String text) {
            // check that the text is a valid numeric representation (or partial representation)
        }
    }
    

    【讨论】:

    • 所以你确认用小数分隔符替换点的假设是有效的?您的解决方案似乎非常好。最后一件事,使用该解决方案,例如用法语输入一个点是不可能的。它总是用逗号代替。那么就没有办法区分用普通键盘输入的点和用小键盘的小数分隔键输入的点了吗?
    • 好吧,也许吧。 :)。我没有足够的国际键盘经验来确定这是否有效;例如,为欧洲语言环境配置的键盘是否仍会产生“。”从数字键盘上的小数点开始,还是他们产生逗号?此外,在某些语言环境中,'.'用作分组分隔符,因此您可能也需要考虑这一点。 KeyCode 枚举具有数字键盘 0-9 键的常量,但“。”之间似乎没有区别。在数字键盘和普通键盘上。简而言之,我没有提供任何确定的东西,但这就是我要开始的地方。
    • 好吧,如果 KeyCode 枚举在键盘上没有用于小数点分隔符的常量,那么我不知道我们会怎么做。无论如何,这个解决方案工作得很好。谢谢
    【解决方案2】:

    在TextField的“setOnKeyPressed”和“setOnKeyReleased”事件中,可以从keyEvent中获取按下的键码,可以看到“.”的键码。从主键盘按下对应于常量“PERIOD”,而击键代码为“.”。从数字小键盘按下对应于常量“DECIMAL”。

    从这个概念,我分享了我在这方面最接近的成就,如果我按下“。”在数字键盘上,根据我的具体需要,我将其替换为字符“,”。

    totalAmountText.setOnKeyReleased((keyEvent) -> {
            if (keyEvent.getCode() == DECIMAL) {
                int pos = totalAmountText.getCaretPosition();
                totalAmountText.setText(totalAmountText.getText().replace(".", ","));
                totalAmountText.positionCaret(pos);
            }
        });
    

    【讨论】:

    • 这不适用于“setOnKeyPressed”,因为在该事件实例中,键入的字符尚未转储到控件中,因此替换功能不会生效。
    • 这是完全错误的,使用 textformatter(使用数字格式来决定允许的字符)是 的方法
    【解决方案3】:

    我附上了一个新版本的代码,它从第一个答案的代码中汲取了最佳实践:

        totalAmountText.setOnKeyReleased((keyEvent) -> {
            if (keyEvent.getCode() == DECIMAL) {
                int pos = totalAmountText.getCaretPosition();
                DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
                totalAmountText.setText(totalAmountText.getText().replace(".", 
                    Character.toString(symbols.getDecimalSeparator())));
                totalAmountText.positionCaret(pos);
            }
        });
    

    【讨论】:

    • 不要重复你的答案 - 而是编辑第一个(这和第一个一样错误,顺便说一句)
    猜你喜欢
    • 2010-10-14
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 2011-02-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多