TextFormatter <T>
is a class that handles "conversion and modification" in the text input control, and is used by setting it in the text input control such as TextField
and TextArea
. It has the following roles.
--Holds a data model of type T
--Handling mutual conversion between text representation and original type T
--Process Change, which is a state change of text input (filter)
TextFormatter holds the data model of the type specified by the type argument T
.
You can retrieve it with getValue ()
and get the property with valueProperty ()
, so you can also do property binding. Also, this value
and the text input control text
will change following each other regardless of which one is rewritten.
StringConverter
For example, if you want to edit Integer type data with TextField
, you need to convert it to a text representation and display it. Also, to treat the edited value as an Integer, you need to parse the text. StringConverter is an interface that provides a framework for such types of interconversion.
JavaFX already has a built-in StringConverter for common types, so you can choose from here to use. Package javafx.util.converter
TextFormatter.Change
TextFormatter.Change
is a class that holds the state change of the text input control. Each time a text input control is ** manipulated **, a Change
is generated and passed to the TextFormatter
. It has the following information.
--Selection range before and after change (caret and anchor position) --The range of text that will be removed by the change --Text inserted after change --Type of change (add, delete, replace) --Whole text before and after the change
TextFormatter.Change (JavaFX): API Document
TextFormatter has the function to process this Change
. In other words, you can replace the changes you don't like with Change
with other changes. In TextFormatter, this operation is called a filter and can be implemented as a functional interface that receives Change
and returns Change
.
UnaryOperator<TextFormatter.Change> filter;
The selection is defined as between the anchor and the caret. The caret is the current position where you are typing, but be aware that it has different implications when it is at the beginning and end of the selection.
TextFormatter is created by passing StringConverter, filter, or both. TextFormatter (JavaFX): API Document
Below is a sample.
Let's use the built-in class CurrencyStringConverter
which displays Number as currency.
Example
TextFormatter<Number> currencyFormatter = new TextFormatter<>(
new CurrencyStringConverter(Locale.JAPAN),
0,
change -> {
//Selection cannot be before the first character
change.setAnchor(Math.max(1, change.getAnchor()));
change.setCaretPosition(Math.max(1, change.getCaretPosition()));
//Text change range cannot be before the first character
change.setRange(Math.max(1, change.getRangeStart()), Math.max(1, change.getRangeEnd()));
return change;
});
textField1.setTextFormatter(currencyFormatter);
"" Is always displayed at the beginning. CurrencyStringConverter performs mutual conversion such as "¥ 100000" → 100000 → "¥ 100,000" when the enter key is pressed, and 100000 is set to value
of TextFormatter
.
Thanks to value
, the representation of the text field and the data model can be treated separately. The following is an example of turning the letters red when the number is 30000 or less.
Example
currencyFormatter.valueProperty().addListener((o, oldValue, newValue) -> {
textField1.setStyle(newValue.intValue() <= 30000 ?
"-fx-text-fill: red" : "-fx-text-fill: black");
});
In addition, a filter is passed to this TextFormatter
so that the first character" \ "cannot be selected, deleted, or changed. Below is a full selection by pressing Ctrl-A.
Example
Pattern notNumberPattern = Pattern.compile("[^0-9]+");
TextFormatter<String> lowerFormatter = new TextFormatter<>(change -> {
String newStr = notNumberPattern.matcher(change.getText()).replaceAll("");
int diffcount = change.getText().length() - newStr.length();
change.setAnchor(change.getAnchor() - diffcount);
change.setCaretPosition(change.getCaretPosition() - diffcount);
change.setText(newStr);
return change;
});
textField2.setTextFormatter(lowerFormatter);
This TextFormatter
is passed only the filter, and it is a mechanism to replace the change difference text with only numbers every time. Below is the text field after typing "2017-04-01T12: 00: 00".
Since the filter converts each update, it works not only by key input but also by copy and paste and value setting by TextField :: setText
.
I made an IPv4 address field where you can enter a numerical value for each byte. You cannot edit anything other than numbers, and typing "." Selects the byte to the right.
Example
textField3.setTextFormatter(new Inet4AddressFormatter(null));
There is a limit to determining the user's mouse operation and key operation from the change difference. If you want to make something elaborate, you should consider another approach.
Since the filter is convenient because it can know only the changed part of the text field at once, it seems that it is often used easily as an alternative to the ChangeListener of the text field.
Yutchi's Blog: I also tried Formatted Text added in JDK8u40. Source: GitHub FXLM: GitHub