How to enforce JTextField to allow only numeric input data of limited length?

Requirement

The text field should only allow numbers and not even decimal points. Also, it must restrict the length of input data.

Code Explanation

In createUI() method as usual an instance of JTextField is created and added to a JPanel. To put restrictions on JTextField javax.swing.text.DocumentFilter is used. DocumentFilter provides a mechanism to apply filter on document associated with swing text components such as JTextField.

 26     public void createUI() {
 27         final JFrame frame = new JFrame("NumericTextField");
 28         frame.setSize(400, 400);
 29         JPanel panel = new JPanel();
 30         JLabel label=new JLabel("Enter some data (only numbers would be allowed):");
 31         final JTextField textField = new JTextField(30);
 32         // Add the document filter to text field for nemric and length check.
 33         ((AbstractDocument) textField.getDocument()).setDocumentFilter(new NumericAndLengthFilter(
 34                 5));
 35         panel.add(label);
 36         panel.add(textField);        
 37         frame.getContentPane().add(panel);
 38         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 39         frame.setVisible(true);
 40     }
    

Notice that NumericAndLengthFilter takes length in the constructor to impose input length restriction on JTextField. Both insertString() and replace() methods are overriden so that not only key input, pasted data from clipboard also can be validated. Both the methods calculate the effective length considering current data on field and new incoming data. If the length is within permissible range the input data is validated for numeric check using a simple number test method.

 55 
 56     /**
 57      * A document filter for numeric and length check.
 58      */
 59     private class NumericAndLengthFilter extends DocumentFilter {
 60 
 61         /**
 62          * Number of characters allowed.
 63          */
 64         private int length = 0;
 65 
 66         /**
 67          * Restricts the number of charcacters can be entered by given length.
 68          * @param length Number of characters allowed.
 69          */
 70         public NumericAndLengthFilter(int length) {
 71             this.length = length;
 72         }
 73 
 74         @Override
 75         public void insertString(FilterBypass fb, int offset, String string,
 76                 AttributeSet attr) throws
 77                 BadLocationException {
 78             if (isNumeric(string)) {
 79                 if (this.length > 0 && fb.getDocument().getLength() + string.
 80                         length()
 81                         > this.length) {
 82                     return;
 83                 }
 84                 super.insertString(fb, offset, string, attr);
 85             }
 86         }
 87 
 88         @Override
 89         public void replace(FilterBypass fb, int offset, int length, String text,
 90                 AttributeSet attrs) throws
 91                 BadLocationException {
 92             if (isNumeric(text)) {
 93                 if (this.length > 0 && fb.getDocument().getLength() + text.
 94                         length()
 95                         > this.length) {
 96                     return;
 97                 }
 98                 super.insertString(fb, offset, text, attrs);
 99             }
100         }
    

The below method checks whether the incoming string is a number. This method does not allow decimal point even. However, this method can be enhanced further as per requirement.

102         /**
103          * This method tests whether given text can be represented as number.
104          * This method can be enhanced further for specific needs.
105          * @param text Input text.
106          * @return {@code true} if given string can be converted to number; otherwise returns {@code false}.
107          */
108         private boolean isNumeric(String text) {
109             if (text == null || text.trim().equals("")) {
110                 return false;
111             }
112             for (int iCount = 0; iCount < text.length(); iCount++) {
113                 if (!Character.isDigit(text.charAt(iCount))) {
114                     return false;
115                 }
116             }
117             return true;
118         }
119     }
120 }
    

In case typed in or copied data is invalid, insert or replace operation is discarded. So, now we successfully implemented a numeric text field with help of a javax.swing.text.DocumentFilter.

Download

You may download the complete source code from here: