简体   繁体   English

在Java TextField中仅接受数字和点

[英]Accept only numbers and a dot in Java TextField

I've got one textField where I only accept numbers from the keyboard, but now I have to change it as it's a "price textField" and I would also need to accept a dot "." 我有一个textField,我只接受键盘上的数字,但是现在我必须更改它,因为它是“ price textField”,我还需要接受一个点“”。 for any kind of prices. 以任何一种价格。

How can I change this in order to get what I need? 我怎样才能改变它以获得我所需要的?

ptoMinimoField = new JTextField();
        ptoMinimoField.setBounds(348, 177, 167, 20);
        contentPanel.add(ptoMinimoField);
        ptoMinimoField.setColumns(10);
        ptoMinimoField.addKeyListener(new KeyAdapter() {
            public void keyTyped(KeyEvent e) {
                char caracter = e.getKeyChar();
                if (((caracter < '0') || (caracter > '9'))
                        && (caracter != '\b')) {
                    e.consume();
                }
            }
        });

As suggested by Oracle , Use Formatted Text Fields 根据Oracle的建议, 使用格式化的文本字段

Formatted text fields provide a way for developers to specify the valid set of characters that can be typed in a text field. 格式化的文本字段为开发人员提供了一种方法,可以指定可以在文本字段中键入的有效字符集。

amountFormat = NumberFormat.getNumberInstance();
...
amountField = new JFormattedTextField(amountFormat);
amountField.setValue(new Double(amount));
amountField.setColumns(10);
amountField.addPropertyChangeListener("value", this);

JTextField txField = new DoubleJTextField(); JTextField txField =新的DoubleJTextField();

Create a file DoubleJTextField.java and be happy 创建一个文件DoubleJTextField.java并高兴

public class DoubleJTextField extends JTextField {
    public DoubleJTextField(){
        addKeyListener(new KeyAdapter() {
            public void keyTyped(KeyEvent e) {
                char ch = e.getKeyChar();

                if (!isNumber(ch) && !isValidSignal(ch) && !validatePoint(ch)  && ch != '\b') {
                    e.consume();
                }
            }
        });

    }

    private boolean isNumber(char ch){
        return ch >= '0' && ch <= '9';
    }

    private boolean isValidSignal(char ch){
        if( (getText() == null || "".equals(getText().trim()) ) && ch == '-'){
            return true;
        }

        return false;
    }

    private boolean validatePoint(char ch){
        if(ch != '.'){
            return false;
        }

        if(getText() == null || "".equals(getText().trim())){
            setText("0.");
            return false;
        }else if("-".equals(getText())){
            setText("-0.");
        }

        return true;
    }
}

I just use a try - catch block: 我只是使用try - catch块:

try {// if is number
    Integer.parseInt(String);
} catch (NumberFormatException e) {
    // else then do blah
}

Don't ever use a KeyListener for this. 永远不要为此使用KeyListener。 Your code above has two serious bugs, both caused by the use of a KeyListener. 上面的代码有两个严重的错误,都由使用KeyListener引起。 First, it will miss any text that gets pasted in. Whenever I find a field that filters out non-digits, I always try to paste in some text, just for fun. 首先,它将丢失任何粘贴的文本。每当我找到一个过滤掉非数字的字段时,我总是尝试粘贴一些文本,只是为了好玩。 Nine times out of ten, the text gets accepted, because they used a key listener. 在十分之九的时间内,文本被接受,因为它们使用了键侦听器。

Second, you didn't filter out modifiers. 其次,您没有过滤掉修饰符。 If the user tries to save their work by typing control-s while they're in this field, your key listener will consume the event. 如果用户在此字段中尝试通过键入control-s来保存其工作,则您的关键侦听器将使用该事件。 And if your application assigns, say, a control-5 or alt-5 shortcut to some action, this KeyListener will add a 5 to the field when they type it, even though the user wasn't trying to type a character. 并且,如果您的应用程序为某个操作分配了control-5或alt-5快捷方式,则即使用户未尝试键入字符,此KeyListener也会在他们键入该字段时为其添加5。 You did figure out that you needed to pass the backspace key, but that's not all you need to pass. 您确实确定需要传递退格键,但这还不是全部。 Your arrow keys won't work. 您的箭头键不起作用。 Neither will your function keys. 您的功能键也不会。 You can fix all these problems, but it starts to be a lot of work. 您可以解决所有这些问题,但是开始工作量很大。

There's a third disadvantage, but it only shows up if you adapt your application to a foreign alphabet, particularly one that takes multiple keystrokes to generate a single character, like Chinese. 还有第三个缺点,但是只有当您使应用程序适应外来字母时才会显示出来,特别是需要多次击键来生成单个字符(例如中文)的外来字母。 These alphabets make KeyListeners useless. 这些字母使KeyListener没有用。

The trouble is this. 麻烦是这个。 You need to filter characters, but KeyListeners aren't about characters, they're about keystrokes, which are not the same thing: Not all keystrokes generate characters, and not all characters are generated by keystrokes. 您需要过滤字符,但是KeyListener与字符无关,它们与击键有关,这不是同一回事:并非所有击键都生成字符,也不是所有字符都由击键生成。 You need an approach that looks at characters after they've been generated, and after modified keystrokes have already been filtered out. 您需要一种方法,可以在生成字符之后以及已滤除修改的击键之后查看字符。

The simplest approach is to use a JFormattedTextField, but I've never liked that approach, because it doesn't format or filter as you type. 最简单的方法是使用JFormattedTextField,但我从未喜欢过这种方法,因为它在您键入时不会格式化或过滤。 So instead, I will use a DocumentFilter. 因此,我将使用DocumentFilter。 DocumentFilters don't operate on keystrokes, they operate on the text strings as they get inserted to your JTextField's data model. DocumentFilters不会对按键进行操作,它们会在插入到JTextField的数据模型中时对文本字符串进行操作。 Hence, all the control-keys, arrow and function keys and such don't even reach the DocumentFilter. 因此,所有控制键,箭头和功能键等都无法到达DocumentFilter。 All pasted text goes through the DocumentFilter, too. 所有粘贴的文本也都通过DocumentFilter。 And, for languages that take three keystrokes to generate a single character, the DocumentFilter doesn't get invoked until the character is generated. 而且,对于需要三次击键才能生成一个字符的语言,直到生成该字符后才调用DocumentFilter。 Here's what it looks like: 看起来是这样的:

    ptoMinimoField = new JTextField();
    ptoMinimoField.setBounds(348, 177, 167, 20); // Don't do this! See below.
    contentPanel.add(ptoMinimoField);
    ptoMinimoField.setColumns(10);

    PlainDocument document = (PlainDocument) ptoMinimoField.getDocument();
    document.setDocumentFilter(new DigitFilter());
}

The DigitFilter class looks like this: DigitFilter类如下所示:

public class DigitFilter extends DocumentFilter {
    @Override
    public void insertString(FilterBypass fb, int offset, String text, 
            AttributeSet attr) throws BadLocationException {
        super.insertString(fb, offset, revise(text), attr);
    }

    @Override
    public void replace(FilterBypass fb, int offset, int length, String text,
                        AttributeSet attrs) throws BadLocationException {
        super.replace(fb, offset, length, revise(text), attrs);
    }

    private String revise(String text) {
        StringBuilder builder = new StringBuilder(text);
        int index = 0;
        while (index < builder.length()) {
            if (accept(builder.charAt(index))) {
                index++;
            } else {
                // Don't increment index here, or you'll skip the next character!
                builder.deleteCharAt(index);
            }
        }
        return builder.toString();
    }

    /**
     * Determine if the character should remain in the String. You may
     * override this to get any matching criteria you want. 
     * @param c The character in question
     * @return true if it's valid, false if it should be removed.
     */
    public boolean accept(final char c) {
        return Character.isDigit(c) || c == '.';
    }
}

You could write this as an inner class, but I created a separate class so you can override the accept() method to use any criteria you want. 您可以将其编写为内部类,但是我创建了一个单独的类,因此可以覆盖accept()方法以使用所需的任何条件。 You may also notice that I don't test for digits by writing this: 您可能还会注意到,我不会通过编写以下代码来测试数字:

(c < '0') || (c > '9')

Instead, I do this: 相反,我这样做:

Character.isDigit()

This is faster, cleaner, and works with foreign numbering systems. 这是更快,更干净的方法,并且可以与外部编号系统一起使用。 I also don't need your test for the backspace character, '\\b'. 我也不需要对退格字符'\\ b'进行测试。 I'm guessing that your first KeyListener was filtering out the backspace key, which was your first clue that it was the wrong approach. 我猜想您的第一个KeyListener正在过滤出退格键,这是您第一个提示这是错误的方法。

And on an unrelated note, don't hard code your component positions. 另外,不要硬编码您的组件位置。 Learn how to use the LayoutManagers. 了解如何使用LayoutManager。 They're easy to use, and they'll make your code much easier to maintain. 它们易于使用,并使您的代码更易于维护。

Have you looked at a JFormattedTextField? 您是否看过JFormattedTextField? It would seem it does what you want. 看来它可以满足您的要求。

Enter the double number of JTextField in java 在Java中输入JTextField的双数

private boolean dot = false;
private void txtMarkKeyTyped(java.awt.event.KeyEvent evt) {                                 
    char vChar = evt.getKeyChar();
    if (txtMark.getText().equals(""))
        dot = false;
    if (dot == false){
        if (vChar == '.') dot = true;
        else if (!(Character.isDigit(vChar)
                || (vChar == KeyEvent.VK_BACK_SPACE)
                || (vChar == KeyEvent.VK_DELETE))) {
                evt.consume();
        }
    } else {
        if (!(Character.isDigit(vChar)
                || (vChar == KeyEvent.VK_BACK_SPACE)
                || (vChar == KeyEvent.VK_DELETE))) {
                evt.consume();
        }
    }
}

This bit of code; 这一段代码;

if (((caracter < '0') || (caracter > '9'))
                    && (caracter != '\b')) {

decides whether to consume the key event. 决定是否使用键事件。 You need to update the condition so it doesn't consume the dot character. 您需要更新条件,以免消耗点字符。

Just right click on TextField / events / key / keytyped 只需右键单击TextField /事件/键/键入

if(!Character.isDigit(evt.getKeyChar())){
            evt.consume();}

///////////// /////////////

    JTextField ptoMinimoField = new JTextField();
    ptoMinimoField.addKeyListener(new KeyAdapter() {
        public void keyTyped(KeyEvent e) {
             boolean ret = true;
                try {

                    Double.parseDouble(ptoMinimoField.getText()+e.getKeyChar());
                }catch (NumberFormatException ee) {
                    ret = false;
                }


            if (!ret) {
                e.consume();
            }
        }
    });

maybe can help you for filtering keytyped just number and dot 也许可以帮助您过滤仅键入数字和点的键类型

public void filterHanyaAngkaDot(java.awt.event.KeyEvent evt){
      char c = evt.getKeyChar();
      if (! ((Character.isDigit(c) ||
              (c == KeyEvent.VK_BACK_SPACE) ||
              (c == KeyEvent.VK_DELETE))
              )&& c==KeyEvent.VK_COMMA
              )
      {
          evt.consume();
      }
 }
JTextField txtMyTextField = new JTextField();

numOnly(txtMyTextField);

public void numOnly(Object objSource){
    ((Component) objSource).addKeyListener(new KeyListener() {

        @Override
        public void keyTyped(KeyEvent e) {
            String filterStr = "0123456789.";
            char c = (char)e.getKeyChar();
            if(filterStr.indexOf(c)<0){
                e.consume();
            }
        }
        @Override
        public void keyReleased(KeyEvent e) {}

        @Override
        public void keyPressed(KeyEvent e) {}
    });
}

WARNING: This function does not follow proper java documentation guide. 警告:此功能未遵循正确的Java文档指南。

I have been using this solution, it's simple and efficient: 我一直在使用此解决方案,它既简单又有效:

                jtextfield.addKeyListener(new KeyAdapter() {
                public void keyTyped(KeyEvent e) {
                    char vChar = e.getKeyChar();
                    if (!(Character.isDigit(vChar)
                            || (vChar == KeyEvent.VK_BACK_SPACE)
                            || (vChar == KeyEvent.VK_DELETE))) {
                        e.consume();
                    }
                }
            });
private boolean point = false;
private void txtProductCostPriceAddKeyTyped(java.awt.event.KeyEvent evt)   
{
    char Char = evt.getKeyChar();
    if (txtProductCostPriceAdd.getText().equals(""))
        point = false;
    if (point == false){
        if (Char == '.') point = true;
        else if (!(Character.isDigit(Char) || (Char == KeyEvent.VK_BACK_SPACE) || (Char == KeyEvent.VK_DELETE))) {
                evt.consume();
        }
    } else {
        if (!(Character.isDigit(Char) || (Char == KeyEvent.VK_BACK_SPACE) || (Char == KeyEvent.VK_DELETE))) {
                evt.consume();
        }
    }
}
JTextField textField = new JTextField();
textField.setColumns(10);

textField.addKeyListener(new KeyAdapter() {
    @Override
    public void KeyTyped(KeyEvent e) {
        if (!(e.getKeyChar() >= '0' && e.getKeyChar() <= '9')) {
            e.consume();
        }
    }
})

this is the easiest method i have found so far, and it works without any error 这是到目前为止我发现的最简单的方法,并且可以正常工作

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM