JavaFX:侦听器的 TextField 最大值和最小值
JavaFX : TextField max and min value by listener
我需要限制文本字段 属性 的文本间隔
int maxLength = 64;
int minLength = 0;
txtSeuil.textProperty().addListener((v, oldValue, newValue) -> {
if (!newValue.matches("\d*")) {
txtSeuil.setText(newValue.replaceAll("[^\d*{1,2}]", ""));
if (txtSeuil.getText().length() > maxLength || txtSeuil.getText().length() < minLength) {
String s = txtSeuil.getText().substring(0, maxLength);
txtSeuil.setText(s);
}
}
});
该字段只接受数字但接受任何数字,而不仅仅是间隔值
要解决您的问题,您可以为 TextFormatter 实施自定义 Filter
。它将只允许输入数字并限制字符串的长度。这是展示它如何工作的片段:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.stage.Stage;
public class Main5 extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
TextField textField = new TextField();
textField.setTextFormatter(new TextFormatter<Integer>(change -> {
if (!change.getText().isEmpty()) {
return change.getText().matches("\d+") && change.getControlNewText().length() <= 5 ? change : null;
}
return change;
}));
primaryStage.setScene(new Scene(textField));
primaryStage.show();
}
}
您的问题是:
如果正则表达式匹配,则不会进行长度检查。但是文本可以是数字序列并且太长了。
您需要独立进行这些检查。
此外,您在某些情况下设置了一个新值,这会再次触发相同的检查。当然,它们会导致 String
被评估为有效输入,但您可以通过在 ChangeListener
中引入一个字段来防止再次检查,该字段存储当前是否正在执行侦听器:
txtSeuil.textProperty().addListener(new ChangeListener<String>() {
private boolean validating = false;
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
if (!validating) {
validating = true;
String newText = newValue;
boolean modify = false;
if (!newValue.matches("\d*")) {
newText = newValue.replaceAll("[^\d*{1,2}]", "");
modify = true;
}
if (newText.length() > maxLength || newText.length() < minLength) {
newText = newText.substring(0, maxLength);
modify = true;
}
if (modify) {
txtSeuil.setText(newText);
}
validating = false;
}
}
});
如果我没理解错的话,您正在尝试实现一个数字字段,该字段只允许区间 [0, 64] 内的值。根据 this answer, TextFormatter
is the recommended way to accomplish such a functionality. Have a look at this MWE 应该可以解决您的问题:
public class RestrictedNumberFieldDemo extends Application {
public static void main(String[] args) {
launch();
}
@Override
public void start(Stage primaryStage) {
TextField numField = new TextField();
numField.setTextFormatter(new TextFormatter<Integer>(change -> {
// Deletion should always be possible.
if (change.isDeleted()) {
return change;
}
// How would the text look like after the change?
String txt = change.getControlNewText();
// There shouldn't be leading zeros.
if (txt.matches("0\d+")) {
return null;
}
// Try parsing and check if the result is in [0, 64].
try {
int n = Integer.parseInt(txt);
return 0 <= n && n <= 64 ? change : null;
} catch (NumberFormatException e) {
return null;
}
}));
primaryStage.setScene(new Scene(numField));
primaryStage.show();
}
}
我需要限制文本字段 属性 的文本间隔
int maxLength = 64;
int minLength = 0;
txtSeuil.textProperty().addListener((v, oldValue, newValue) -> {
if (!newValue.matches("\d*")) {
txtSeuil.setText(newValue.replaceAll("[^\d*{1,2}]", ""));
if (txtSeuil.getText().length() > maxLength || txtSeuil.getText().length() < minLength) {
String s = txtSeuil.getText().substring(0, maxLength);
txtSeuil.setText(s);
}
}
});
该字段只接受数字但接受任何数字,而不仅仅是间隔值
要解决您的问题,您可以为 TextFormatter 实施自定义 Filter
。它将只允许输入数字并限制字符串的长度。这是展示它如何工作的片段:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.stage.Stage;
public class Main5 extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
TextField textField = new TextField();
textField.setTextFormatter(new TextFormatter<Integer>(change -> {
if (!change.getText().isEmpty()) {
return change.getText().matches("\d+") && change.getControlNewText().length() <= 5 ? change : null;
}
return change;
}));
primaryStage.setScene(new Scene(textField));
primaryStage.show();
}
}
您的问题是:
如果正则表达式匹配,则不会进行长度检查。但是文本可以是数字序列并且太长了。
您需要独立进行这些检查。
此外,您在某些情况下设置了一个新值,这会再次触发相同的检查。当然,它们会导致 String
被评估为有效输入,但您可以通过在 ChangeListener
中引入一个字段来防止再次检查,该字段存储当前是否正在执行侦听器:
txtSeuil.textProperty().addListener(new ChangeListener<String>() {
private boolean validating = false;
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
if (!validating) {
validating = true;
String newText = newValue;
boolean modify = false;
if (!newValue.matches("\d*")) {
newText = newValue.replaceAll("[^\d*{1,2}]", "");
modify = true;
}
if (newText.length() > maxLength || newText.length() < minLength) {
newText = newText.substring(0, maxLength);
modify = true;
}
if (modify) {
txtSeuil.setText(newText);
}
validating = false;
}
}
});
如果我没理解错的话,您正在尝试实现一个数字字段,该字段只允许区间 [0, 64] 内的值。根据 this answer, TextFormatter
is the recommended way to accomplish such a functionality. Have a look at this MWE 应该可以解决您的问题:
public class RestrictedNumberFieldDemo extends Application {
public static void main(String[] args) {
launch();
}
@Override
public void start(Stage primaryStage) {
TextField numField = new TextField();
numField.setTextFormatter(new TextFormatter<Integer>(change -> {
// Deletion should always be possible.
if (change.isDeleted()) {
return change;
}
// How would the text look like after the change?
String txt = change.getControlNewText();
// There shouldn't be leading zeros.
if (txt.matches("0\d+")) {
return null;
}
// Try parsing and check if the result is in [0, 64].
try {
int n = Integer.parseInt(txt);
return 0 <= n && n <= 64 ? change : null;
} catch (NumberFormatException e) {
return null;
}
}));
primaryStage.setScene(new Scene(numField));
primaryStage.show();
}
}