Issue
I want to create a numeric TextField which will be localized.
For example, in Excel, if you are in english, if you type a number with the KeyPad, the decimal separator key will enter a dot '.' But if you are in French, the decimal separator will be a comma ','
Therefore in Excel, the TextField is smart enough to detect in which Locale you're on, and to adapt the decimal separator you actually wanted to print in the TextField.
Right now in JavaFX, I haven't found a way to do that. I was thinking of listening to text modification and to replace any occurrence of dot with a comma if I detect I'm in French. But is this assumption true?
Solution
I would recommend subclassing TextField
and overriding the insertText
and replace*
methods. This will handle text entry before the text is updated; listening to text modifications and fixing them will mean you temporarily have "invalid" text in your text field's text property, which could create problems in the rest of your application.
Note that you can create a java.text.DecimalFormatSymbols
object for the default (user) Locale
(or a specified Locale
, if you need), and call getDecimalSeparator()
to find the correct decimal separator character. (Similarly, you can call getGroupingSeparator()
.)
So, for proof of concept, this is nowhere near robust enough for production:
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)
}
}
Answered By - James_D