控制键盘输入到javafx TextField

时间:2013-10-03 19:35:02

标签: java javafx

我想控制输入到Javafx TextField中,这样我就只允许输入数字,这样如果超出了最大字符数,那么就不会对文本框进行任何更改。

编辑:根据评论中的建议,我使用了JavaFX项目负责人建议的方法。它可以很好地阻止输入字母。我只是需要它来过滤特殊字符。我尝试将过滤器更改为(text.matchs(“[0-9]”),但不允许输入退格。

edit2:找出特殊字符和长度的过滤器。这是我的最终代码。感谢输入人员。

这是我创建的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);
        }
    }
}

注意:我已阅读此帖子What is the recommended way to make a numeric TextField in JavaFX?,此解决方案对我不起作用。它只会在输入数字后被触发。这意味着某人可以在框中键入字母文本,并允许它直到他们将焦点移离文本字段。此外,他们可以输入大于允许数量的数字,但验证不会发生在每个按键上,而是在焦点转移后('更改'事件)。

6 个答案:

答案 0 :(得分:8)

最好的方法是:

    @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();
            }
        }
    };
}    
/*****************************************************************************************/

祝你好运。

答案 1 :(得分:4)

这是我的aproach,两个事件过滤器,可能是一个,在我的情况下,我在不同的情况下使用它们,这就是为什么有两个。

这是maxValueFilter(在spanglish 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();
            }

        }
    }

另一个事件过滤器(过滤字符),这个是一个方法:

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;
    }

在您的情况下使用将是:

field.addEventFilter(KeyEvent.KEY_TYPED,
                numFilter());
field.addEventFilter(KeyEvent.KEY_TYPED, new FiltroValorMaximo(
                99));

答案 2 :(得分:2)

最终解决方案。不允许使用字母和特殊字符并强制执行字符限制。

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);
        }
    }
}

答案 3 :(得分:2)

我只是设置'On Key Typed'事件来运行这个小程序:

    @FXML public void processKeyEvent(KeyEvent ev) {
    String c = ev.getCharacter();
    if("1234567890".contains(c)) {}
    else {
        ev.consume();
    }
}

它就像一个冠军!

答案 4 :(得分:2)

我创建了一个可以添加到Java Builder FX的自定义Textfield(使用&#39;导入JAR / FXML文件...&#39;)。

可以设置此TextField

  1. 允许的字符或数字
  2. 如果有空格字符
  3. 如果输入仅为CAPITAL(显示的输出为大写)
  4. 和长度。
  5. 当然可以改进,但它非常有用。 希望这会有所帮助:)

    FX Project LimitedTextField 有了这个项目就可以创建出来的'LimitedTextField.jar&#39;要在您的应用程序或java builder FX中导入的文件。

    CustomControlExample.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

    <?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

    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;
        }
    }
    

    使用示例:

    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

    ...
    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);
    }
    

    再见

答案 5 :(得分:0)

尝试此解决方案在控制器中添加此功能,您必须将其添加到文本字段的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]", ""));
            }
        }
    });
}