java 如何限制 TextField 使其只能包含一个 '.' 特点?JavaFX
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31458198/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to restrict TextField so that it can contain only one '.' character? JavaFX
提问by void
On the Internet, I found very useful class, using which I can restrict TextField. I encountered a problem, where my TextField can contain only one '.' character. I suspect that I can handle this by writing an appripriate regex and set it as a restriction on the instance of that class. I use the following regex: "[0-9.-]", but it allows as many dots as the user types. May I ask you to help me to configure my TextField so that no more than one '.' is allowed.
在网上,我发现了一个非常有用的类,使用它我可以限制TextField。我遇到了一个问题,我的 TextField 只能包含一个 '.' 特点。我怀疑我可以通过编写一个适当的正则表达式来处理这个问题,并将其设置为对该类实例的限制。我使用以下正则表达式:“[0-9.-]”,但它允许用户输入尽可能多的点。我可以请你帮我配置我的 TextField 以便不超过一个 '.' 被允许。
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.TextField;
/**
* Created by Anton on 7/14/2015.
*/
public class RestrictiveTextField extends TextField {
private IntegerProperty maxLength = new SimpleIntegerProperty(this, "maxLength", -1);
private StringProperty restrict = new SimpleStringProperty(this, "restrict");
public RestrictiveTextField() {
super("0");
textProperty().addListener(new ChangeListener<String>() {
private boolean ignore;
@Override
public void changed(ObservableValue<? extends String> observableValue, String s, String s1) {
if (ignore || s1 == null)
return;
if (maxLength.get() > -1 && s1.length() > maxLength.get()) {
ignore = true;
setText(s1.substring(0, maxLength.get()));
ignore = false;
}
if (restrict.get() != null && !restrict.get().equals("") && !s1.matches(restrict.get() + "*")) {
ignore = true;
setText(s);
ignore = false;
}
}
});
}
/**
* The max length property.
*
* @return The max length property.
*/
public IntegerProperty maxLengthProperty() {
return maxLength;
}
/**
* Gets the max length of the text field.
*
* @return The max length.
*/
public int getMaxLength() {
return maxLength.get();
}
/**
* Sets the max length of the text field.
*
* @param maxLength The max length.
*/
public void setMaxLength(int maxLength) {
this.maxLength.set(maxLength);
}
/**
* The restrict property.
*
* @return The restrict property.
*/
public StringProperty restrictProperty() {
return restrict;
}
/**
* Gets a regular expression character class which restricts the user input.
*
* @return The regular expression.
* @see #getRestrict()
*/
public String getRestrict() {
return restrict.get();
}
/**
* Sets a regular expression character class which restricts the user input.
* E.g. [0-9] only allows numeric values.
*
* @param restrict The regular expression.
*/
public void setRestrict(String restrict) {
this.restrict.set(restrict);
}
}
}
回答by James_D
There are various versions of the regex, depending on exactly what you want to support. Note that you don't only want to match valid numbers, but also partial entries, because the user has to be able to edit this. So, for example, an empty string is not a valid number, but you certainly want the user to be able to delete everything that's there while they are editing; similarly you want to allow "0."
, etc.
正则表达式有多种版本,具体取决于您想要支持的内容。请注意,您不仅要匹配有效数字,还要匹配部分条目,因为用户必须能够对其进行编辑。因此,例如,空字符串不是有效数字,但您当然希望用户能够在编辑时删除其中的所有内容;同样,您希望允许"0."
等。
So you probably want something like
所以你可能想要类似的东西
Optional minus sign, followed by eitherany number of digits, orat least one digit, a period (.
), and any number of digits.
可选的减号,随后任一的任何数量的数字,或至少一个数字,句点(.
),并且任何数量的数字。
The regex for this could be -?((\\d*)|(\\d+\.\\d*))
. There are probably other ways to do this, some of them perhaps more efficient. And if you want to support exponential forms ("1.3e12"
) it gets more complex.
这个的正则表达式可能是-?((\\d*)|(\\d+\.\\d*))
. 可能还有其他方法可以做到这一点,其中一些可能更有效。如果您想支持指数形式 ( "1.3e12"
),它会变得更加复杂。
To use this with a TextField
, the recommended way is to use a TextFormatter
. The TextFormatter
consists of two things: a converter to convert between the text and the value it represents (a Double
in your case: you can just use the built-in DoubleStringConverter
), and vice versa, and then a filter. The filter is implemented as a function that takes a TextFormatter.Change
object and returns an object of the same type. Typically you either leave the Change
object as it is and return it (to accept the Change
"as is"), or modify it somehow. It is also legal to return null
to represent "no change". So in your simple case here, just examine the new proposed text, see if it matches the regular expression, return the change "as is" if it matches and return null
otherwise.
要将其与 a 一起使用TextField
,推荐的方法是使用 a TextFormatter
。在TextFormatter
包括两个方面:一个转换器将文字和它所代表的价值之间的转换(一个Double
在你的情况:你可以使用内置的DoubleStringConverter
),反之亦然,然后过滤。过滤器被实现为一个函数,它接受一个TextFormatter.Change
对象并返回一个相同类型的对象。通常,您要么保持Change
对象原样,然后返回它(以接受Change
“原样”),要么以某种方式修改它。返回null
代表“没有变化”也是合法的。因此,在您这里的简单情况下,只需检查新提议的文本,查看它是否与正则表达式匹配,如果匹配则返回“原样”更改,null
否则返回。
Example:
例子:
import java.util.regex.Pattern;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.converter.DoubleStringConverter;
public class NumericTextFieldExample extends Application {
@Override
public void start(Stage primaryStage) {
TextField textField = new TextField();
Pattern validDoubleText = Pattern.compile("-?((\d*)|(\d+\.\d*))");
TextFormatter<Double> textFormatter = new TextFormatter<Double>(new DoubleStringConverter(), 0.0,
change -> {
String newText = change.getControlNewText() ;
if (validDoubleText.matcher(newText).matches()) {
return change ;
} else return null ;
});
textField.setTextFormatter(textFormatter);
textFormatter.valueProperty().addListener((obs, oldValue, newValue) -> {
System.out.println("New double value "+newValue);
});
StackPane root = new StackPane(textField);
root.setPadding(new Insets(24));
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
回答by Codebender
You can use the following regex,
您可以使用以下正则表达式,
"[^\.]*\.{0,1}[^\.]"
Or as VGR has pointed out, "A period has no special meaning inside character class brackets and 0 or 1 time can be represented with a '?' (question mark).", so you can also use,
或者正如 VGR 指出的那样,“句号在字符类括号内没有特殊含义,0 或 1 次可以用 '?' 表示。(问号)。” , 所以你也可以使用,
"[^.]*\.?[^.]"
I don't know why but your class seems to append a *
to the regex, so the above regex will effectively become,
我不知道为什么,但你的班级似乎*
在正则表达式中附加了 a ,所以上面的正则表达式将有效地变成,
"[^\.]*\.{0,1}[^\.]*"
Which means,
意思是,
- It will allow any character except a
.
0 or more times (greedy). - It will allow a
.
0 or 1 times. - It will allow any character except a
.
0 or more times (greedy).
- 它将允许任何字符,除了
.
0 次或更多次(贪婪)。 - 它将允许
.
0 或 1 次。 - 它将允许任何字符,除了
.
0 次或更多次(贪婪)。
This is what you seem to be needing. DEMO
这就是你似乎需要的。演示
回答by GregH
{[0-9]+\.[0-9]+}
to match any number if this is in fact what you are wanting to do
如果这实际上是您想要做的,则匹配任何数字