如何创建一个数字本地化(小数点分隔符)TextField?

问题描述 投票:1回答:3

我想创建一个本地化的数字TextField。

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

因此,在Excel中,TextField足够聪明,可以检测到你在哪个Locale上,并适应你实际上想要在TextField中打印的小数点分隔符。

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

javafx javafx-8
3个回答
1
投票

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

请注意,您可以在您的应用程序中创建一个 java.text.DecimalFormatSymbols 对象的默认 Locale (或指定的 Locale,如果您需要的话),并拨打 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)
    }
}

-1
投票

在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);
        }
    });

-1
投票

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

    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);
        }
    });
© www.soinside.com 2019 - 2024. All rights reserved.