Michael Pickett Michael Pickett - 1 month ago 4x
Java Question

How to match true and false using TextFormatter in java

Some backstory. I am using textformatting to filter input into a textfield. I have one for numbers only, one for alphanumeric characters, one for numbers with decimal. This should ne letters only, and only match "true" or "false" case insensitive. The code I have below will allow ONLY those letters to be typed, which is functionality I want, but it will not match in order.

UnaryOperator<TextFormatter.Change> filterBoolean = (TextFormatter.Change t) -> {
if (t.isReplaced()) {
if (t.getText().matches("[^tTrRuUFfAaLlSsEe]")) {
t.setText(t.getControlNewText().substring(t.getRangeStart(), t.getRangeEnd()));
} else if (t.isAdded()) {
if (t.getText().matches("[^tTrRuUFfAaLlSsEe]")) {
} else if (t.getText().matches("[^tTrRuUFfAaLlSsEe]")) {
return t;
getTextField().setTextFormatter(new TextFormatter<>(formatter));

I have tried to use this functionality by separating them adding

|| t.getControlNewText().matches("[tT][rR][uU][eE]|[fF][aA][lL][sS][eE]")
|| t.getControlNewText().matches("[^([tT][rR][uU][eE]|[fF][aA][lL][sS][eE])]")
|| t.getControlNewText().matches("^([tT][rR][uU][eE]|[fF][aA][lL][sS][eE])")

to each t.getText() line, but it does not seem to work.
I have similiar text formatters that will allow any alphanumeric character up to X times, but those are not order sensitive.

So my question is, how can I edit my code to allow for order sensitive input of a textfield, where I only want to match "true" and "False", case insensitive?


As noted in the comment, you should almost certainly consider using a different control for this, such as a check box or other kind of toggle button.

If you want to go this route, you need to think about what would be valid while the user is still editing (not just when editing is complete). So, e.g. the user might delete from any position in the text "true" or "false". Conceivably, they might also start typing, say "true" before deleting "false".

So you probably want something like

UnaryOperator<TextFormatter.Change> filterBoolean = (TextFormatter.Change t) -> {
    String testText = t.getControlNewText().toLowerCase();
    if ("truefalse".contains(testText) || "falsetrue".contains(testText)) {
        return t ;
    // otherwise veto:
    return null ;

If you wanted to be a bit stricter (but probably more annoying for the user), you could just do if ("true".contains(testText) || "false".contains(testText)), etc. You could be even more sophisticated, e.g. you could delete all the text if there is any delete operation (since that is likely the intention of the user).

In either case, you would then need additional validation when the user commits (probably on pressing Enter or on loss of keyboard focus).

Again, it's a much better user experience just to use a control specifically designed for this use case.