JTextField limiting character amount input and accepting numeric only

前端 未结 7 1258

here\'s the code that i have on how to limit the character input length

class JTextFieldLimit extends PlainDocument {
  private int limit;
  // optional uppe         


        
7条回答
  •  情书的邮戳
    2020-11-28 00:05

    You're on the right track, except you will want to use a DocumentFilter instead of implementing your own document.

    MDP's Weblog has a number of excellent examples (including limiting the length and character type).

    Now to the your question, you could create cascading filter, where you could chain a series of filters together.

    This would allow you to call each filter in turn.

    public class ChainableFilter extends DocumentFilter {
    
        private List filters;
        private AttributeSet attr;
    
        public ChainableFilter() {
            filters = new ArrayList(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);
            }
        }
    
    }
    

    Now it would be nice if filter could actually tell the chain if it altered the document at all, but I'll leave that up to you

    UPDATED

    The basic concept between what you've done and how DocumentFilters work is pretty much the same. The benefit is, you're not limiting your self to a PlainDocument, you could, in theory, apply it to a JTextPane or JEditorPane.

    The basic idea of the filter chain is simple.

    ChainableFilter chainableFilter = new ChainableFilter();
    chainableFilter.addFilter(new RestrictedLengthFilter()); // User supplied filter 
    chainableFilter.addFilter(new NumericFilter()); // User supplied filter 
    
    ((AbstractDocument)textField.getDocument()).setDocumentFilter(chainableFilter);
    

    As for the actual filters, I'd check out the link I posted earlier. You're on the right track with your ideas though

    UPDATED

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

    Again, I know it compiles, but I've not tested it (the numeric filter in particular), but that would be a good exercise in debugging ;)

提交回复
热议问题