JTextField限制字符数量输入并仅接受数字

时间:2012-10-09 04:55:28

标签: java swing jtextfield documentfilter

这是我有关如何限制字符输入长度的代码

class JTextFieldLimit extends PlainDocument {
  private int limit;
  // optional uppercase conversion
  private boolean toUppercase = false;

  JTextFieldLimit(int limit) {
   super();
   this.limit = limit;
   }

  JTextFieldLimit(int limit, boolean upper) {
   super();
   this.limit = limit;
   toUppercase = upper;
   }

    @Override
  public void insertString
    (int offset, String  str, AttributeSet attr)
      throws BadLocationException {
   if (str == null) return;

   if ((getLength() + str.length()) <= limit) {
     if (toUppercase) str = str.toUpperCase();
     super.insertString(offset, str, attr);
     }
   }
}

可以通过txtSample.setDocument(new JTextFieldLimit(30));

实施

这就是我只接受数字的原因(虽然我不需要,但它接受小数)

class NumericDocument extends PlainDocument {

     protected int decimalPrecision = 0;
     protected boolean allowNegative = false;


     public NumericDocument(int decimalPrecision, boolean allowNegative) {
          super();
          this.decimalPrecision = decimalPrecision;
          this.allowNegative = allowNegative;
     }



    @Override
     public void insertString(int offset, String str, AttributeSet attr) throws BadLocationException {
          if (str != null){
               if (StringFormat.isNumeric(str) == false && str.equals(".") == false && str.equals("-") == false){ //First, is it a valid character?
                    Toolkit.getDefaultToolkit().beep();
                    return;
               }
               else if (str.equals(".") == true && super.getText(0, super.getLength()).contains(".") == true){ //Next, can we place a decimal here?
                    Toolkit.getDefaultToolkit().beep();
                    return;
               }
               else if (StringFormat.isNumeric(str) == true && super.getText(0, super.getLength()).indexOf(",") != -1 && offset>super.getText(0, super.getLength()).indexOf(",") && super.getLength()-super.getText(0, super.getLength()).indexOf(".")>decimalPrecision && decimalPrecision > 0){ //Next, do we get past the decimal precision limit?
                    Toolkit.getDefaultToolkit().beep();
                    return;
               }
               else if (str.equals("-") == true && (offset != 0 || allowNegative == false)){ //Next, can we put a negative sign?
                    Toolkit.getDefaultToolkit().beep();
                    return;
               }


               super.insertString(offset, str, attr);
          }
          return;
     }
public static class StringFormat
{
    public StringFormat()
    {
    }
    public static boolean isNumeric(String str)
    {
        try
        {
            int x = Integer.parseInt(str);
            System.out.println(x); return true;
        } catch(NumberFormatException nFE)
        {
            System.out.println("Not an Integer"); return false;
        }
    }
}

}

以及如何使用此代码:txtSample.setDocument(new NumericDocument(0,false));

现在问题是txtSample只能setDocument一次。如何限制jtextfield长度并仅在同一时间接受数字?或者有更简单的方法吗?谢谢。 :d

7 个答案:

答案 0 :(得分:9)

您正走在正确的轨道上,除非您想要使用DocumentFilter而不是实施自己的文档。

MDP's Weblog有很多很好的例子(包括限制长度和字符类型)。

现在问题,您可以创建级联过滤器,您可以将一系列过滤器链接在一起。

这样您就可以依次调用每个过滤器。

public class ChainableFilter extends DocumentFilter {

    private List<DocumentFilter> filters;
    private AttributeSet attr;

    public ChainableFilter() {
        filters = new ArrayList<DocumentFilter>(25);
    }

    public void addFilter(DocumentFilter filter) {
        filters.add(filter);
    }

    public void removeFilter(DocumentFilter filter) {
        filters.remove(filter);
    }

    public void insertString(DocumentFilter.FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
        for (DocumentFilter filter : filters) {
            filter.insertString(fb, offset, string, attr);
        }
    }        

    public void remove(DocumentFilter.FilterBypass fb, int offset, int length) throws BadLocationException {
        for (DocumentFilter filter : filters) {
            filter.remove(fb, offset, length);
        }
    }

    public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
        for (DocumentFilter filter : filters) {
            filter.replace(fb, offset, length, text, attrs);
        }
    }

}

现在,如果过滤器实际上可以告诉链是否它根本改变了文档,那将会很好,但是我会把它留给你

<强>已更新

您所做的事情与DocumentFilters的工作方式之间的基本概念几乎相同。好处是,您不能将自己限制在PlainDocument,理论上,您可以将其应用于JTextPaneJEditorPane

过滤器链的基本思想很简单。

ChainableFilter chainableFilter = new ChainableFilter();
chainableFilter.addFilter(new RestrictedLengthFilter()); // User supplied filter 
chainableFilter.addFilter(new NumericFilter()); // User supplied filter 

((AbstractDocument)textField.getDocument()).setDocumentFilter(chainableFilter);

对于实际过滤器,我查看我之前发布的链接。尽管如此,您仍然可以通过您的想法走上正轨

<强>已更新

SizeFilter sizeFilter = new SizeFilter(12);
NumberFilter numFilter = new NumberFilter();
ChainableFilter chainFilter = new ChainableFilter();
chainFilter.addFilter(sizeFilter);
chainFilter.addFilter(numFilter);

JTextField field = new JTextField();
((AbstractDocument) field.getDocument()).setDocumentFilter(chainFilter);



    public class NumberFilter extends DocumentFilter {

        private int decimalPrecision = 2;
        private boolean allowNegative = false;

        public NumberFilter() {
        }

        public NumberFilter(int decimals, boolean negatives) {
            decimalPrecision = decimals;
            allowNegative = negatives;
        }

        protected boolean accept(FilterBypass fb, int offset, String str) throws BadLocationException {
            boolean accept = true;    
            int length = fb.getDocument().getLength();
            String currentText = fb.getDocument().getText(0, length);

            if (str != null) {
                if (!isNumeric(str) && !str.equals(".") && !str.equals("-")) { //First, is it a valid character?
                    Toolkit.getDefaultToolkit().beep();
                    accept = false;
                } else if (str.equals(".") && currentText.contains(".")) { //Next, can we place a decimal here?
                    Toolkit.getDefaultToolkit().beep();
                    accept = false;
                } else if (isNumeric(str)
                                && currentText.indexOf(",") != -1
                                && offset > currentText.indexOf(",")
                                && length - currentText.indexOf(".") > decimalPrecision
                                && decimalPrecision > 0) { //Next, do we get past the decimal precision limit?
                    Toolkit.getDefaultToolkit().beep();
                    accept = false;
                } else if (str.equals("-") && (offset != 0 || !allowNegative)) { //Next, can we put a negative sign?
                    Toolkit.getDefaultToolkit().beep();
                    accept = false;
                }
            }
            return accept;
        }

        @Override
        public void insertString(FilterBypass fb, int offset, String str, AttributeSet as) throws BadLocationException {
            if (accept(fb, offset, str)) {
                super.insertString(fb, offset, str, as);
            }
        }

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

        public boolean isNumeric(String str) {
            try {
                int x = Integer.parseInt(str);
                System.out.println(x);
                return true;
            } catch (NumberFormatException nFE) {
                System.out.println("Not an Integer");
                return false;
            }
        }
    }

    public class SizeFilter extends DocumentFilter {

        private int maxCharacters;

        public SizeFilter(int maxChars) {
            maxCharacters = maxChars;
        }

        public void insertString(FilterBypass fb, int offs, String str, AttributeSet a)
                        throws BadLocationException {

            if ((fb.getDocument().getLength() + str.length()) <= maxCharacters) {
                super.insertString(fb, offs, str, a);
            } else {
                Toolkit.getDefaultToolkit().beep();
            }
        }

        public void replace(FilterBypass fb, int offs, int length, String str, AttributeSet a)
                        throws BadLocationException {

            if ((fb.getDocument().getLength() + str.length()
                     - length) <= maxCharacters) {
                super.replace(fb, offs, length, str, a);
            } else {
                Toolkit.getDefaultToolkit().beep();
            }
        }
    }

同样,我知道它编译,但我没有测试过(特别是数字过滤器),但这在调试中是一个很好的练习;)

答案 1 :(得分:2)

JFormattedTextField

 JTextComponent txt = new JFormattedTextField( new LimitedIntegerFormatter(limit) );
  txt.addPropertyChangeListener("value", yourPropertyChangeListener);


import javax.swing.text.DefaultFormatter;
import java.text.ParseException;

public class LimitedIntegerFormatter extends DefaultFormatter {

  static final long serialVersionUID = 1l;
  private int limit;

  public LimitedIntegerFormatter( int limit ) {
    this.limit = limit;
    setValueClass(Integer.class);
    setAllowsInvalid(false);
    setCommitsOnValidEdit(true);
  }
  @Override
  public Object stringToValue(String string) throws ParseException {
    if (string.equals("")) return null;
    if (string.length() > limit) throw new ParseException(string, limit);
    return super.stringToValue(string);
  }
}

将使用

调用yourPropertyChangeListener

new PropertyChangeEvent(“value”,Integer oldValue,Integer newValue)

(oldValue或newValue在“”文本案例中)为空

每次有效编辑后

答案 2 :(得分:1)

    import java.awt.event.KeyAdapter;    
    import java.awt.event.KeyEvent;    
    import javax.swing.JTextField;        

    public class Validation {

         public static void validateInt(final JTextField txt){
            txt.addKeyListener(new KeyAdapter() {

                   @Override
                   public void keyTyped(KeyEvent e) {
                        char c = e.getKeyChar();
                        if ( ((c < '0') || (c > '9')) 
                             && (c != KeyEvent.VK_BACK_SPACE)) {
                        e.consume();  // ignore event
                   }
               }
            });
        }

        public static void validatelength(final JTextField txt,final int size){    
              txt.addKeyListener(new KeyAdapter() {

              @Override 
              public void keyTyped(KeyEvent e) {     
                  String text = txt.getText();  
                  int length = text.length();  
                  if (length == size) {  
                          e.consume();// ignore event  
                  }
              }   
        });
     }  
   }

答案 3 :(得分:1)

public static boolean validateInt(String txt) {

    String regx = "^[(0-9),;]+$";
    Pattern pattern = Pattern.compile(regx, Pattern.CASE_INSENSITIVE);
    Matcher matcher = pattern.matcher(txt);
    boolean b = matcher.find();
    return b;

}

答案 4 :(得分:0)

我目前正在开发一个带有数独求解器的小项目。我通过检查输入是否在带有数字的字符串数组中来限制我的输入仅限于数字。我直接在JTextFieldLimit中写了它。

class JTextFieldLimit extends PlainDocument {

    private int limit;

    //Added the following 2 lines
    String[] numbers = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
    boolean isAccepted = false;
    //

    JTextFieldLimit(int limit) {
        super();
        this.limit = limit;
    }

    public void insertString(int offset, String str, AttributeSet attr) throws BadLocationException {
        if (str == null)
            return;

        //And the following 2 lines
        for (String thisnumber : numbers) {
            isAccepted = str.equals(thisnumber);
            if (isAccepted) {
                //
                if ((getLength() + str.length()) <= limit) {
                    super.insertString(offset, str, attr);
                }
            }
        }
    }
}

答案 5 :(得分:0)

import java.awt.Component;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.DocumentFilter;
import javax.swing.text.JTextComponent;
import org.apache.commons.lang.StringUtils;

public class NumberTextField extends JTextField {

    protected int maxlength = 0;

    public NumberTextField() {
        this(10);
    }

    public NumberTextField(int length) {
        super();
        this.maxlength = length;
        initializeForNumbers();
    }

    public void setMaxLength(int length) {
        this.maxlength = length;
    }

    protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
        int keyCode = e.getKeyCode();
        if (keyCode == KeyEvent.VK_ENTER || keyCode == KeyEvent.VK_ESCAPE) {
            return false;
        }
        return super.processKeyBinding(ks, e, condition, pressed);
    }

    private void initializeForNumbers() {
        Document document = getDocument();
        if (document != null) {
            ((AbstractDocument) document).setDocumentFilter(new DocumentHandler());
        }
    }

    private class DocumentHandler extends DocumentFilter {

        public void insertString(DocumentFilter.FilterBypass fb,
                int offset, String string, AttributeSet attr)
                throws BadLocationException {
            if (string == null) {
                return;
            } else {
                replace(fb, offset, 0, string, attr);
            }

        }

        public void remove(DocumentFilter.FilterBypass fb,
                int offset, int length)
                throws BadLocationException {

            replace(fb, offset, length, "", null);
        }

        public void replace(final DocumentFilter.FilterBypass fb,
                int offset, int length, String text, AttributeSet attrs)
                throws BadLocationException {

            Document doc = fb.getDocument();
            int currentLength = doc.getLength();
            String currentContent = doc.getText(0, currentLength);
            String before = currentContent.substring(0, offset);
            String after = currentContent.substring(length + offset, currentLength);
            String newValue = before + (text == null ? "" : text) + after;
            if (newValue.length() > maxlength) {
                return;
            } else {
                checkInput(newValue, offset);
                fb.replace(offset, length, text, attrs);

                if (doc.getLength() >= maxlength) {
                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            Component c = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
                            if (c != null && c instanceof JTextComponent) {
                                JTextComponent component = (JTextComponent) c;
                                Document compDoc = component.getDocument();
                                if (compDoc.equals(fb.getDocument())) {
                                    KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent();
                                }
                            }
                        }
                    });
                    return;
                }
            }
        }

        private void checkInput(String proposedValue, int offset)
                throws BadLocationException {
            if (proposedValue.length() > 0 && !StringUtils.isNumeric(proposedValue)) {
                throw new BadLocationException(
                        proposedValue, offset);
            }
        }
    }
}

答案 6 :(得分:-1)

yourJTextField.addKeyListener(new KeyAdapter()
        {
            @Override
            public void keyTyped(KeyEvent e)
            {
                // Here limiting the character of your number. for examlpe this wil only accept one digit
                if (yourJTextField.getText().length() == 1) {
                    e.consume();
                }

                // Here limiting your input to only number
                char c = e.getKeyChar();
                if(!((c >= '0') && (c <= '7') || (c == KeyEvent.VK_BACK_SPACE) || (c == KeyEvent.VK_DELETE)))
                {
                    //do what so ever you want
                }
                else
                {
                    //do what so ever you want
                }
            }
        })