Обновление 27 мая 2016 г.
Java 8u40 представила класс TextFormatter , который является рекомендуемым способом реализации этой функции (хотя решение, предоставленное в этом ответе, все еще будетРабота).Для получения дополнительной информации см. ответ Уве , ответ Хасана и другие ответы с упоминанием TextFormatter на следующий вопрос:
Существует также это решение из другого ответа на этот вопрос, который я не пробовал, но выглядит хорошо и модератор StackOverflow удален:
TextField numberField = new TextField();
numberField.setTextFormatter(new TextFormatter<>(new NumberStringConverter()));
Приведенный выше код пропускает фильтр UnaryOperator для TextFormatter, который обычно также требуется (в противном случае поле не будет отображать ограничение ввода пользователем только отформатированного значения, оно просто позволит вам отслеживать неформатированное значение черезсвойство значения форматеров текста).Чтобы расширить решение для использования фильтра, можно использовать код, подобный приведенному ниже:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.stage.Stage;
import javafx.util.converter.NumberStringConverter;
import java.text.ParsePosition;
import java.util.function.UnaryOperator;
public class NumberConverterFieldTest extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage stage) {
TextField numberField = new TextField();
NumberStringFilteredConverter converter = new NumberStringFilteredConverter();
final TextFormatter<Number> formatter = new TextFormatter<>(
converter,
0,
converter.getFilter()
);
numberField.setTextFormatter(formatter);
formatter.valueProperty().addListener((observable, oldValue, newValue) ->
System.out.println(newValue)
);
stage.setScene(new Scene(numberField));
stage.show();
}
class NumberStringFilteredConverter extends NumberStringConverter {
// Note, if needed you can add in appropriate constructors
// here to set locale, pattern matching or an explicit
// type of NumberFormat.
//
// For more information on format control, see
// the NumberStringConverter constructors
// DecimalFormat class
// NumberFormat static methods for examples.
// This solution can instead extend other NumberStringConverters if needed
// e.g. CurrencyStringConverter or PercentageStringConverter.
public UnaryOperator<TextFormatter.Change> getFilter() {
return change -> {
String newText = change.getControlNewText();
if (newText.isEmpty()) {
return change;
}
ParsePosition parsePosition = new ParsePosition( 0 );
Object object = getNumberFormat().parse( newText, parsePosition );
if ( object == null || parsePosition.getIndex() < newText.length()) {
return null;
} else {
return change;
}
};
}
}
}
При запуске приведенного выше примера отредактируйте поле ввода и нажмите клавишу ввода, чтобы увидеть обновленное значение (обновленное значениевыведите в System.out
при изменении).
Обучающее руководство см .:
Это то же решение, на которое ссылается Урс, однако я просто поместил его в полностью исполняемую программу, чтобы предоставить пример в контексте, и изменил регулярное выражение (добавив *
кконец), так что копирование и вставка работает, и это не имеет проблемы, на которую ссылается Улук.Решение кажется довольно простым и, вероятно, будет достаточным для большинства целей:
import java.util.regex.Pattern;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
public class NumericTextFieldTest extends Application {
public static void main(String[] args) { launch(args); }
@Override public void start(Stage stage) {
TextField numberField = new TextField() {
@Override public void replaceText(int start, int end, String text) {
if (text.matches("[0-9]*")) {
super.replaceText(start, end, text);
}
}
@Override public void replaceSelection(String text) {
if (text.matches("[0-9]*")) {
super.replaceSelection(text);
}
}
};
stage.setScene(new Scene(numberField));
stage.show();
}
}
Альтернативные решения
Вас также может заинтересовать мое альтернативное решение в JavaFXПример привязки значения ползунка к редактируемому TextField .В этом решении я расширяю TextField, чтобы выставить IntegerProperty на поле для целей простого связывания.Альтернативное решение аналогично предложенному исходным постером в их обновленном вопросе (т. Е. Добавлен фильтр событий, чтобы ограничить входные данные от ключевых событий), но дополнительно к списку свойств TextField добавлен ChangeListener, чтобы обеспечить копирование и вставку значений.принимаются только в том случае, если они числовые.
Существуют и другие решения этого вопроса в ветке форума JavaFX Числовое текстовое поле в JavaFX 2.0? , которое включает ссылку на числовые поля из управления FXExperience .