Normalerweise finde ich es einfacher, den resultierenden Text aus einer Änderung zu überprüfen ; Geben Sie die Änderung "wie sie ist" zurück, wenn sie in Ordnung ist, und geben Sie andernfalls null zurück. Hier soll der resultierende Text ein optionales negatives Vorzeichen, null oder mehr Ziffern, ein Optionen-Dezimaltrennzeichen und null oder mehr Ziffern sein. (Hinweis: Dies ermöglicht eine beliebige gültige Gleitkommazahl oder eine leere Zeichenfolge oder ein negatives Vorzeichen oder digitalen Separator auf seine eigene.)
So für den Filter:
UnaryOperator<TextFormatter.Change> filter = new UnaryOperator<TextFormatter.Change>() {
@Override
public TextFormatter.Change apply(TextFormatter.Change t) {
String newText = t.getControlNewText() ;
if (newText.matches("-?[0-9]*\\.?[0-9]*")) {
return t ;
}
return null ;
}
};
Sie auch einen Konverter definieren können, die Sie mit dem Spinner selbst und dem Textfeld, das der Editor für den Spinner ist, verwenden können. Dies muss nur die Zeichenfolge als Doppelklick analysieren, sollte aber die Sonderfälle -
, .
und -.
behandeln. Also:
StringConverter<Double> converter = new StringConverter<Double>() {
@Override
public String toString(Double object) {
return object.toString() ;
}
@Override
public Double fromString(String string) {
if (string.isEmpty() || ".".equals(string) || "-".equals(string) || "-.".equals(string)) {
return 0.0 ;
} else {
return new Double(string);
}
}
};
dann tun
svf.setConverter(converter);
spinner.getEditor().setTextFormatter(new TextFormatter<>(converter, 0.0, filter));
Dieser Konverter richtig leere Strings behandelt zu interpretieren, etc, wie 0.0
, und so wird die Ausnahme vermeiden, wenn Sie versuchen, oder -abnahme zu erhöhen, wenn der Editor im dieser Staat.
SSCCE:
import java.util.function.UnaryOperator;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Spinner;
import javafx.scene.control.SpinnerValueFactory;
import javafx.scene.control.TextFormatter;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.StringConverter;
public class SpinnerTest extends Application {
@Override
public void start(Stage primaryStage) {
SpinnerValueFactory<Double> svf = new SpinnerValueFactory.DoubleSpinnerValueFactory(-500,500,1,0.5);
Spinner<Double> spinner = new Spinner<>();
spinner.setValueFactory(svf);
spinner.setEditable(true);
UnaryOperator<TextFormatter.Change> filter = new UnaryOperator<TextFormatter.Change>() {
@Override
public TextFormatter.Change apply(TextFormatter.Change t) {
String newText = t.getControlNewText() ;
if (newText.matches("-?[0-9]*\\.?[0-9]*")) {
return t ;
}
return null ;
}
};
StringConverter<Double> converter = new StringConverter<Double>() {
@Override
public String toString(Double object) {
return object.toString() ;
}
@Override
public Double fromString(String string) {
if (string.isEmpty() || ".".equals(string) || "-".equals(string) || "-.".equals(string)) {
return 0.0 ;
} else {
return new Double(string);
}
}
};
svf.setConverter(converter);
spinner.getEditor().setTextFormatter(new TextFormatter<>(converter, 0.0, filter));
StackPane root = new StackPane(spinner);
primaryStage.setScene(new Scene(root, 180, 80));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Vielen Dank für Ihre Hilfe und wirklich gute Erklärung. Es hat das Problem gelöst. –