如何在JavaFX中强制在文本字段中进行双重输入?
如何确保用户在给定的文本字段中只输入两个值 我找到了一个bu,我不能用它来打双打。我应该写什么来代替如何在JavaFX中强制在文本字段中进行双重输入?,java,javafx,input,textfield,Java,Javafx,Input,Textfield,如何确保用户在给定的文本字段中只输入两个值 我找到了一个bu,我不能用它来打双打。我应该写什么来代替“\\d*”和“[^\\d]”,以使其适用于双打 textField.textProperty().addListener(new ChangeListener<String>() { @Override public void changed(ObservableValue<? extends String> observable, String oldV
“\\d*”
和“[^\\d]”
,以使其适用于双打
textField.textProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
if (!newValue.matches("\\d*")) {
textField.setText(newValue.replaceAll("[^\\d]", ""));
}
}
});
textField.textProperty().addListener(新的ChangeListener()){
@凌驾
public void changed(observeValue您可以使用Double.parseDouble。这将为您进行解析,而不是编写自己的双重验证。然后您可以检查数字格式异常或空指针异常
try
{
Double.parseDouble(newValue);
// Valid double
}
catch (NullPointerException | NumberFormatException ex)
{
// Not valid double
}
您可以在双精度上使用java正则表达式,并将非数字字符替换为数字。在中,您必须指定整数部分允许的位数,例如1,10
textField.textProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
if (!newValue.matches("[0-9]{<range>}(\\.[0-9]*)?")) {
textField.setText(newValue.replaceAll("[^\\d.]", ""));
StringBuilder aus = new StringBuilder(newValue);
boolean firstPointFound = false;
for (int i = 0; i < aus.length(); i++){
if(aus.charAt(i) == '.') {
if(!firstPointFound)
firstPointFound = true;
else
aus.deleteCharAt(i);
}
}
newValue = aus.toString();
}
}
});
textField.textProperty().addListener(新的ChangeListener()){
@凌驾
更改公众假期(ObservalEvalue如果用户输入了无效值,则使用侦听器并恢复为有效值的方法将起作用,但如果文本字段的textProperty
上有其他侦听器,则可能会产生问题。这些侦听器将观察无效值和有效值,因此他们必须知道如何过滤掉任何输入有效值
更好的方法是使用。TextFormatter
可以做两件事:
定义一个“过滤器”,它可以否决或修改对文本字段
文本所做的任何更改
定义一个“转换器”,它定义了在您的案例中如何将文本转换为任何特定类型的值(例如,Double
)
定义适当的筛选器可能很棘手:您希望允许用户进行任何合理的编辑。这意味着在用户编辑时文本可能处于无效状态;例如,您可能希望允许文本字段完全为空,即使这并不表示有效值。(否则,例如,如果用户希望将“1”更改为“2”,则会让用户感到恼火。)类似地,您可能希望允许“-”和“.”等内容
下面是一个示例。如果需要,筛选器应该修改传递给它的更改,并且可以返回null
以完全否决更改。此示例仅检查文本是否表示有效的编辑状态,如果表示有效的编辑状态,则返回未经修改的更改,否则将予以否决。格式化程序需要处理所有允许的文本wed被过滤器连接并将其转换为double。在这里,任何不完整的都表示为零
Pattern validEditingState = Pattern.compile("-?(([1-9][0-9]*)|0)?(\\.[0-9]*)?");
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) || "-.".equals(s)) {
return 0.0 ;
} else {
return Double.valueOf(s);
}
}
@Override
public String toString(Double d) {
return d.toString();
}
};
TextFormatter<Double> textFormatter = new TextFormatter<>(converter, 0.0, filter);
TextField textField = new TextField();
textField.setTextFormatter(textFormatter);
这是一个SSCCE。第二个文本字段就在那里,以便您可以看到将焦点移动到其他控件的效果(如果值已更改,它“提交”该值并调用文本格式化程序上的侦听器;如果用户按enter键,则会发生类似的情况)
import java.util.function.UnaryOperator;
导入java.util.regex.Pattern;
导入javafx.application.application;
导入javafx.beans.value.observeValue;
导入javafx.geometry.Pos;
导入javafx.scene.scene;
导入javafx.scene.control.TextField;
导入javafx.scene.control.TextFormatter;
导入javafx.scene.layout.VBox;
导入javafx.stage.stage;
导入javafx.util.StringConverter;
公共类NumericTextField扩展了应用程序{
@凌驾
public void start(Stage primaryStage)引发异常{
Pattern validitingstate=Pattern.compile(“-?([1-9][0-9]*)0)?(\\\[0-9]*)?”;
一元运算符筛选器=c->{
String text=c.getControlNewText();
if(validEditingState.matcher(text.matches()){
返回c;
}否则{
返回null;
}
};
StringConverter转换器=新的StringConverter(){
@凌驾
公共双fromString(字符串s){
如果(s.isEmpty()| |“-”。等于(s)| |。”。等于(s)| |“-。。等于(s)){
返回0.0;
}否则{
返回两倍。值为;
}
}
@凌驾
公共字符串到字符串(双d){
返回d.toString();
}
};
TextFormatter TextFormatter=新的TextFormatter(转换器,0.0,过滤器);
TextField TextField=新的TextField();
setTextFormatter(textFormatter);
textFormatter.valueProperty().addListener((Observalevalue感谢您的回答,但是如果我尝试输入99.99。
在第二次
时,我会收到一个错误(而且输入更改为9999
)。你知道如何解决这个问题吗?谢谢你的回答,但我正在尝试强制用户只输入双精度值。我希望避免管理无效输入。强制用户输入双精度值的唯一方法是检测无效输入。对正则表达式匹配执行if或将上述代码拉入测试之间没有区别返回true或false的Double方法。“强制用户输入Double的唯一方法是检测无效的输入。”不正确。例如,您可以重写各种insert
方法,或者使用TextFormatter
。使用异常处理进行逻辑控制也是一种非常糟糕的做法。异常应该是针对异常情况,而不是您期望在正常事件运行中发生的情况。使用Double.parse与任何手动p一样糟糕模式匹配:无区域设置感知。至少,您必须在TextFormatter中使用NumberFormat…,正如@James_DDon所建议的那样,不要使用侦听器;text属性的其他观察者将在还原之前看到无效输入。请改为使用TextFormatter
。不要进行任何手动模式匹配,它将在大多数非默认情况下中断-美国/英国地区。。
// update text field:
double value = ... ;
textFormatter.setValue(value);
// listen for changes in double value represented in text field
// Listener will be invoked when the user commits an edit:
textFormatter.valueProperty().addListener((ObservableValue<? extends Double> obs, Double oldValue, Double newValue) -> {
System.out.println("User entered value: "+newValue.doubleValue());
});
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.stage.Stage;
import javafx.util.StringConverter;
public class NumericTextField extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
Pattern validEditingState = Pattern.compile("-?(([1-9][0-9]*)|0)?(\\.[0-9]*)?");
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) || "-.".equals(s)) {
return 0.0 ;
} else {
return Double.valueOf(s);
}
}
@Override
public String toString(Double d) {
return d.toString();
}
};
TextFormatter<Double> textFormatter = new TextFormatter<>(converter, 0.0, filter);
TextField textField = new TextField();
textField.setTextFormatter(textFormatter);
textFormatter.valueProperty().addListener((ObservableValue<? extends Double> obs, Double oldValue, Double newValue) -> {
System.out.println("User entered value: "+newValue.doubleValue());
});
VBox root = new VBox(5, textField, new TextField());
root.setAlignment(Pos.CENTER);
primaryStage.setScene(new Scene(root, 250, 250));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}