5

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

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

这就是我只接受数字的内容(它接受十进制,尽管 w/ci 不需要)

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

4

7 回答 7

9

你走在正确的轨道上,除了你会想要使用DocumentFilter而不是实现你自己的文档。

MDP 的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工作方式之间的基本概念几乎相同。好处是,您不会将自己限制在 aPlainDocument上,理论上您可以将其应用于 a JTextPaneor JEditorPane

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

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

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

于 2012-10-09T05:05:52.833 回答
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 将被调用

新的 PropertyChangeEvent(“值”,整数 oldValue,整数 newValue)

( oldValue 或 newValue 在 "" 文本案例中将为空)

每次有效编辑后

于 2012-11-16T10:09:33.030 回答
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  
                  }
              }   
        });
     }  
   }
于 2013-03-07T20:43:42.990 回答
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;

}
于 2013-03-07T21:21:40.430 回答
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);
            }
        }
    }
}
于 2015-12-02T10:53:44.397 回答
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);
                }
            }
        }
    }
}
于 2015-12-02T10:28:32.023 回答
-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
                }
            }
        })
于 2012-12-17T12:33:47.703 回答