Я не мог сопротивляться. Это ответ на две строки (те, которые выполняют всю работу)
private static TextFormatter<Double> new3DecimalFormatter(){
Pattern decimalPattern = Pattern.compile("-?\\d*(\\.\\d{0,3})?");
return new TextFormatter<>(c -> (decimalPattern.matcher(c.getControlNewText()).matches()) ? c : null );
}