控制键盘输入到 javafx TextField
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19167750/
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
Control keyboard input into javafx TextField
提问by Damienknight
I want to control the input into a Javafx TextField so that I can allow only Numeric input, and so that if the max characters are exceeded, then no change will be made to the textbox.
我想控制 Javafx TextField 的输入,以便我只能允许数字输入,并且如果超过最大字符数,则不会对文本框进行任何更改。
edit: Based on a recommendation in the comments, I used the method suggested by the JavaFX project lead. It works great to stop letters from being entered. I just need it to also filter special characters. I tried changing the filter to (text.matchs("[0-9]") but that did not allow backspace to be entered.
编辑:根据评论中的建议,我使用了 JavaFX 项目负责人建议的方法。阻止输入字母非常有效。我只需要它来过滤特殊字符。我尝试将过滤器更改为 (text.matchs("[0-9]") 但这不允许输入退格。
edit2: Figured out a filter on special chars and length. Here is my final code. Thanks for the input fellas.
edit2:找出特殊字符和长度的过滤器。这是我的最终代码。感谢输入的家伙。
Here is the TextField class i have created:
这是我创建的 TextField 类:
import javafx.scene.control.TextField;
public class AttributeTextField extends TextField{
public AttributeTextField() {
setMinWidth(25);
setMaxWidth(25);
}
public void replaceText(int start, int end, String text) {
String oldValue = getText();
if (!text.matches("[a-z]") && !text.matches("[\\!\"#$%&()*+,./:;<=>?@\[\]^_{|}~]+")) {
super.replaceText(start, end, text);
}
if (getText().length() > 2 ) {
setText(oldValue);
}
}
public void replaceSelection(String text) {
String oldValue = getText();
if (!text.matches("[a-z]") && !text.matches("[\\!\"#$%&()*+,./:;<=>?@\[\]^_{|}~]+")) {
super.replaceSelection(text);
}
if (getText().length() > 2 ) {
setText(oldValue);
}
}
}
Note: I have read What is the recommended way to make a numeric TextField in JavaFX?this post, and this solution does not work for me. It only gets fired after the number has been entered. Meaning someone could type alphabetic text into the box, and it would allow it until they moved focus away from the textfield. Also, they can enter numbers larger than allowed, but validation happens not on each keypress, but instead after focus shift ('changed' event).
注意:我已阅读在 JavaFX 中创建数字 TextField 的推荐方法是什么?这篇文章,这个解决方案对我不起作用。只有在输入号码后才会被触发。这意味着有人可以在框中键入字母文本,并且在他们将焦点从文本字段移开之前它会允许它。此外,他们可以输入大于允许的数字,但验证不是在每次按键时进行,而是在焦点转移('changed' 事件)之后进行。
采纳答案by Damienknight
Final solution. Disallows alphabetic and special characters and enforces character limit.
最终解决方案。不允许使用字母和特殊字符并强制执行字符限制。
import javafx.scene.control.TextField;
public class AttributeTextField extends TextField{
public AttributeTextField() {
setMinWidth(25);
setMaxWidth(25);
}
public void replaceText(int start, int end, String text) {
String oldValue = getText();
if (!text.matches("[A-Za-z]") && !text.matches("[\\!\"#$%&()*+,./:;<=>?@\[\]^_{|}~]+")) {
super.replaceText(start, end, text);
}
if (getText().length() > 2 ) {
setText(oldValue);
}
}
public void replaceSelection(String text) {
String oldValue = getText();
if (!text.matches("[A-Za-z]") && !text.matches("[\\!\"#$%&()*+,./:;<=>?@\[\]^_{|}~]+")) {
super.replaceSelection(text);
}
if (getText().length() > 2 ) {
setText(oldValue);
}
}
}
回答by Magcus
Here is my aproach, two event filters, could be one, in my case i used them in diferent situations, thats why there are two.
这是我的方法,两个事件过滤器,可以是一个,就我而言,我在不同的情况下使用它们,这就是为什么有两个。
Here is the maxValueFilter (in spanglish xD), this one is a class:
这是 maxValueFilter(在西班牙语 xD 中),这是一个类:
public class FilterMaxValue implements EventHandler<KeyEvent> {
private int maxVal;
public FilterMaxValue (int i) {
this.maxVal= i;
}
public void handle(KeyEvent arg0) {
TextField tx = (TextField) arg0.getSource();
String chara = arg0.getCharacter();
if (tx.getText().equals(""))
return;
Double valor;
if (chara.equals(".")) {
valor = Double.parseDouble(tx.getText() + chara + "0");
} else {
try {
valor = Double.parseDouble(tx.getText() + chara);
} catch (NumberFormatException e) {
//The other filter will prevent this from hapening
return;
}
}
if (valor > maxVal) {
arg0.consume();
}
}
}
And the other event filter (filters the chars), this one is a method:
而另一个事件过滤器(过滤字符),这是一种方法:
public static EventHandler<KeyEvent> numFilter() {
EventHandler<KeyEvent> aux = new EventHandler<KeyEvent>() {
public void handle(KeyEvent keyEvent) {
if (!"0123456789".contains(keyEvent.getCharacter())) {
keyEvent.consume();
}
}
};
return aux;
}
the use in your case would be:
您的情况的用途是:
field.addEventFilter(KeyEvent.KEY_TYPED,
numFilter());
field.addEventFilter(KeyEvent.KEY_TYPED, new FiltroValorMaximo(
99));
回答by MagicJ
the best way is :
最好的方法是:
@FXML
private TextField txt_Numeric;
@FXML
private TextField txt_Letters;
@Override
public void initialize(URL url, ResourceBundle rb) {
/* add Event Filter to your TextFields **************************************************/
txt_Numeric.addEventFilter(KeyEvent.KEY_TYPED , numeric_Validation(10));
txt_Letters.addEventFilter(KeyEvent.KEY_TYPED , letter_Validation(10));
}
/* Numeric Validation Limit the characters to maxLengh AND to ONLY DigitS *************************************/
public EventHandler<KeyEvent> numeric_Validation(final Integer max_Lengh) {
return new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent e) {
TextField txt_TextField = (TextField) e.getSource();
if (txt_TextField.getText().length() >= max_Lengh) {
e.consume();
}
if(e.getCharacter().matches("[0-9.]")){
if(txt_TextField.getText().contains(".") && e.getCharacter().matches("[.]")){
e.consume();
}else if(txt_TextField.getText().length() == 0 && e.getCharacter().matches("[.]")){
e.consume();
}
}else{
e.consume();
}
}
};
}
/*****************************************************************************************/
/* Letters Validation Limit the characters to maxLengh AND to ONLY Letters *************************************/
public EventHandler<KeyEvent> letter_Validation(final Integer max_Lengh) {
return new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent e) {
TextField txt_TextField = (TextField) e.getSource();
if (txt_TextField.getText().length() >= max_Lengh) {
e.consume();
}
if(e.getCharacter().matches("[A-Za-z]")){
}else{
e.consume();
}
}
};
}
/*****************************************************************************************/
Best of luck.
祝你好运。
回答by Michael Sims
I simply set the 'On Key Typed' event to run this small procedure:
我只是设置了“On Key Typed”事件来运行这个小程序:
@FXML public void processKeyEvent(KeyEvent ev) {
String c = ev.getCharacter();
if("1234567890".contains(c)) {}
else {
ev.consume();
}
}
It works like a champ!
它就像一个冠军!
回答by Matteo
I have created a customized Textfield that can be added to Java Builder FX (using 'import JAR/FXML file...').
我创建了一个可以添加到 Java Builder FX 的自定义文本字段(使用“导入 JAR/FXML 文件...”)。
With this TextField can be set
用这个 TextField 可以设置
- the characters or numbers allowed
- if there is or not the space character
- if the input is only CAPITAL (the shown output is in capital)
- and the lenght.
- 允许的字符或数字
- 如果有或没有空格字符
- 如果输入仅为大写(显示的输出为大写)
- 和长度。
Of course can be improoved, but it's quite usefull. Hope that this will help someone :)
当然可以改进,但它非常有用。希望这会帮助某人:)
FX Project LimitedTextFieldWith this project can be created the 'LimitedTextField.jar' file to import in your application or in java builder FX.
FX 项目 LimitedTextField使用此项目可以创建“LimitedTextField.jar”文件以导入您的应用程序或 java builder FX。
CustomControlExample.java
自定义控件示例.java
package limitedtextfield;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class CustomControlExample extends Application {
@Override
public void start(Stage stage) throws Exception {
LimitedTextField customControl = new LimitedTextField();
customControl.setText("Hello!");
stage.setScene(new Scene(customControl));
stage.setTitle("Custom Control");
stage.setWidth(300);
stage.setHeight(200);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
custom_control.fxml
custom_control.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<HBox>
<limitedtextfield.LimitedTextField text="Hello World!"/>
</HBox>
LimitedTextField.java
LimitedTextField.java
package limitedtextfield;
import javafx.scene.control.TextField;
public class LimitedTextField extends TextField
{
private String characters;
private int max;
private boolean capital = false;
private boolean space = true;
static public final String CharactersNumbers = "[qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890èéòàùì ]";
static public final String Characters = "[qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNMèéòàùì ]";
static public final String Numbers = "[1234567890 ]";
static public final String NumbersPoint = "[1234567890. ]";
public LimitedTextField(String l){
super();
characters = l;
max=0;
}
public LimitedTextField(){
super();
characters = "";
max=0;
}
public LimitedTextField(String l, int max){
super();
characters = l;
this.max=max;
//System.out.println("Costruttore");
}
public LimitedTextField(int max){
super();
characters = "";
this.max=max;
}
@Override
public void replaceText(int start, int end, String text)
{
if(!characters.equals("")){
if (validateCh(text))
{
text = check(text);
super.replaceText(start, end, text);
if(max>0)
verifyLengh();
}
}else{
text = check(text);
super.replaceText(start, end, text);
if(max>0)
verifyLengh();
}
}
@Override
public void replaceSelection(String text)
{
if(!characters.equals("")){
if (validateCh(text))
{
text = check(text);
super.replaceSelection(text);
if(max>0)
verifyLengh();
}
}else{
text = check(text);
super.replaceSelection(text);
if(max>0)
verifyLengh();
}
}
private boolean validateCh(String text)
{
/*
[abc] Find any of the characters between the brackets
[0-9] Find any of the digits between the brackets
(x|y) Find any of the alternatives separated with |
*/
return ("".equals(text) || text.matches(characters));
}
private void verifyLengh() {
if (getText().length() > max) {
setText(getText().substring(0, max));//use this line if you want to delete the newer characters inserted
//setText(getText().substring(getText().length()-max, getText().length()));//use this line if you want to delete the older characters inserted
positionCaret(max);//set the cursor position
}
}
private String check(String text){
if(capital)
text = text.toUpperCase();
if(!space)
text = text.replace(" ", "");
return text;
}
public void setLimitCharachters(String s){
this.characters = s;
}
public String getLimitCharachters(){
return characters;
}
public void setMaxLenght(int s){
this.max= s;
}
public int getMaxLenght(){
return max;
}
public boolean getCapital(){
return this.capital;
}
public void setCapital(boolean t){
this.capital = t;
}
public boolean getSpace(){
return this.space;
}
public void setSpace(boolean t){
this.space = t;
}
}
Example of use:
使用示例:
MyFxmlApplication.fxml
MyFxmlApplication.fxml
...
<?import limitedtextfield.*?>
...
<HBox alignment="CENTER_LEFT" spacing="5.0">
<children>
<Label text="Name:" />
<LimitedTextField fx:id="A_Name_S" />
</children>
<FlowPane.margin>
<Insets right="5.0" />
</FlowPane.margin>
</HBox>
...
MyFxmlApplicationController.fxml
MyFxmlApplicationController.fxml
...
import limitedtextfield.LimitedTextField;
@FXML
private LimitedTextField A_Name_S;
...
@Override
public void initialize(URL url, ResourceBundle rb) {
A_Name_S.setSpace(false);
A_Name_S.setCapital(true);
A_Name_S.setMaxLenght(20);
A_Name_S.setLimitCharachters(LimitedTextField.Characters);
}
bye
再见
回答by Matteo
Try this solution add this function in your controller , you must add it on the keyPressed Action of your text field.
尝试此解决方案在您的控制器中添加此功能,您必须将其添加到文本字段的 keyPressed Action 上。
@FXML
void verifnum(KeyEvent event) {
txt.textProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue,
String newValue) {
if (!newValue.matches("\d*")) {
txt.setText(newValue.replaceAll("[^\d]", ""));
}
}
});
}