在 JavaFX 数字 TextField 中处理无穷大
Handling Infinity in JavaFX numerical TextField
我有一个 JavaFX TextField
专门用于接受数字,包括科学记数法。它几乎可以做我想做的一切。但是,因为它接受科学计数法,所以用户很容易输入超出 double
可以表示的范围的数字。当他们这样做时,TextField
显示“Infinity”(或“-Infinity”)。发生这种情况时,无法再编辑该字段来更正问题。也不能选择和删除内容。点击“Escape”键不会return到之前的内容。
这是一个 SSCCE,它与几年前 by James_D to this 密切相关。
import java.text.DecimalFormatSymbols;
import java.util.function.UnaryOperator;
import java.util.regex.Pattern;
import javafx.application.Application;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.StringConverter;
public class NumericTextFieldDemo extends Application {
char sep = new DecimalFormatSymbols().getDecimalSeparator();
String negStarter = new StringBuilder("-").append(sep).toString();
String posStarter = new StringBuilder("+").append(sep).toString();
String patternStr = new StringBuilder()
.append("[+|-]?(([1-9][0-9]*)|0)?(\")
.append(sep)
.append("[0-9]*)?(([e|E][+|-]?[0-9]*)?)")
.toString();
Pattern validEditingState = Pattern.compile(patternStr);
class NumericTextField extends TextField {
UnaryOperator<TextFormatter.Change> filter = c -> {
String text = c.getControlNewText();
if (validEditingState.matcher(text).matches()) {
return c;
} else {
return null;
}
};
StringConverter<Double> converter = new StringConverter<Double>() {
@Override
public Double fromString(String s) {
if (s.isEmpty() || "-".equals(s) || "+".equals(s)
|| negStarter.equals(s) || posStarter.equals(s)) {
return 0.0;
} else {
return Double.valueOf(s);
}
}
@Override
public String toString(Double d) {
return d.toString();
}
};
NumericTextField(double initValue) {
TextFormatter<Double> textFormatter = new TextFormatter<>(converter, initValue, filter);
textFormatter.valueProperty().addListener((ObservableValue<? extends Double> obs, Double oldValue, Double newValue) -> {
System.out.println("User entered value: " + newValue);
});
setTextFormatter(textFormatter);
}
NumericTextField() {
this(0.0);
}
}
@Override
public void start(Stage primaryStage) throws Exception {
NumericTextField ntf = new NumericTextField();
// Setting the font seems to be required on macOS.
ntf.setFont(new Font("Arial", 14));
VBox root = new VBox(5, ntf);
root.setAlignment(Pos.CENTER);
primaryStage.setScene(new Scene(root, 250, 150));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
有什么方法可以捕获无穷大并使 TextField
处于可用状态吗?是否可以对 class 进行一些更改以防止首先输入此类数字?
只需为双打使用内置的字符串转换器:
TextFormatter<Double> tf = new TextFormatter<>(new DoubleStringConverter());
TextField ntf = new TextField();
ntf.setTextFormatter(tf);
我有一个 JavaFX TextField
专门用于接受数字,包括科学记数法。它几乎可以做我想做的一切。但是,因为它接受科学计数法,所以用户很容易输入超出 double
可以表示的范围的数字。当他们这样做时,TextField
显示“Infinity”(或“-Infinity”)。发生这种情况时,无法再编辑该字段来更正问题。也不能选择和删除内容。点击“Escape”键不会return到之前的内容。
这是一个 SSCCE,它与几年前
import java.text.DecimalFormatSymbols;
import java.util.function.UnaryOperator;
import java.util.regex.Pattern;
import javafx.application.Application;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.StringConverter;
public class NumericTextFieldDemo extends Application {
char sep = new DecimalFormatSymbols().getDecimalSeparator();
String negStarter = new StringBuilder("-").append(sep).toString();
String posStarter = new StringBuilder("+").append(sep).toString();
String patternStr = new StringBuilder()
.append("[+|-]?(([1-9][0-9]*)|0)?(\")
.append(sep)
.append("[0-9]*)?(([e|E][+|-]?[0-9]*)?)")
.toString();
Pattern validEditingState = Pattern.compile(patternStr);
class NumericTextField extends TextField {
UnaryOperator<TextFormatter.Change> filter = c -> {
String text = c.getControlNewText();
if (validEditingState.matcher(text).matches()) {
return c;
} else {
return null;
}
};
StringConverter<Double> converter = new StringConverter<Double>() {
@Override
public Double fromString(String s) {
if (s.isEmpty() || "-".equals(s) || "+".equals(s)
|| negStarter.equals(s) || posStarter.equals(s)) {
return 0.0;
} else {
return Double.valueOf(s);
}
}
@Override
public String toString(Double d) {
return d.toString();
}
};
NumericTextField(double initValue) {
TextFormatter<Double> textFormatter = new TextFormatter<>(converter, initValue, filter);
textFormatter.valueProperty().addListener((ObservableValue<? extends Double> obs, Double oldValue, Double newValue) -> {
System.out.println("User entered value: " + newValue);
});
setTextFormatter(textFormatter);
}
NumericTextField() {
this(0.0);
}
}
@Override
public void start(Stage primaryStage) throws Exception {
NumericTextField ntf = new NumericTextField();
// Setting the font seems to be required on macOS.
ntf.setFont(new Font("Arial", 14));
VBox root = new VBox(5, ntf);
root.setAlignment(Pos.CENTER);
primaryStage.setScene(new Scene(root, 250, 150));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
有什么方法可以捕获无穷大并使 TextField
处于可用状态吗?是否可以对 class 进行一些更改以防止首先输入此类数字?
只需为双打使用内置的字符串转换器:
TextFormatter<Double> tf = new TextFormatter<>(new DoubleStringConverter());
TextField ntf = new TextField();
ntf.setTextFormatter(tf);