33

How to limit the number of characters entered in a JTextField?

Suppose I want to enter say 5 characters max. After that no characters can be entered into it.

Jonas
  • 121,568
  • 97
  • 310
  • 388
Santosh V M
  • 1,541
  • 7
  • 25
  • 41
  • 3
    Although using a custom Document will work, the preferred approach to this solution is to use either JFormattedTextField or to use a DocumentFilter. These are both features that have been added to the JDK in version 1.3 I believe. The Swing tutorial covers both of these approaches (and even removed the custom Document approach from the tutorial). – camickr Aug 19 '10 at 14:43
  • FYI Since Java 1.4, it is no longer required and recommended that you utilise the `Document` for this functionality, instead use a `DocumentFilter`, see [Implementing a Document Filter](http://docs.oracle.com/javase/tutorial/uiswing/components/generaltext.html#filter) and [DocumentFilter Examples](http://www.jroller.com/dpmihai/entry/documentfilter) for more details – MadProgrammer Jan 27 '16 at 22:11

8 Answers8

42

http://www.rgagnon.com/javadetails/java-0198.html

import javax.swing.text.PlainDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;

public class JTextFieldLimit extends PlainDocument {
  private int limit;

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

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

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

Then

import java.awt.*;
import javax.swing.*;

 public class DemoJTextFieldWithLimit extends JApplet{
   JTextField textfield1;
   JLabel label1;

   public void init() {
     getContentPane().setLayout(new FlowLayout());
     //
     label1 = new JLabel("max 10 chars");
     textfield1 = new JTextField(15);
     getContentPane().add(label1);
     getContentPane().add(textfield1);
     textfield1.setDocument
        (new JTextFieldLimit(10));
     }
}

(first result from google)

CrazyVideoGamer
  • 754
  • 8
  • 22
tim_yates
  • 167,322
  • 27
  • 342
  • 338
  • 2
    is there no direct function like textfield.maximumlimit(10); – Santosh V M Aug 19 '10 at 07:25
  • No, and it tells you to use a class that extends `PlainDocument` in the javadoc for `JTextField` http://download.oracle.com/javase/6/docs/api/javax/swing/JTextField.html – tim_yates Aug 19 '10 at 08:04
  • I'm getting two errors when I enter the above mentioned code. 1 - package com.sun.java.swing.text does not exist 2 - cannot find symbol PlainDocument – Santosh V M Aug 19 '10 at 09:06
  • thanks tim_yates for the help will check it out now. will this JTextFieldLimit class work even for password field also? – Santosh V M Aug 19 '10 at 09:34
  • By the way could you please explain how the character limiting takes place through the "JTextFieldLimit" class. It will be helpful. – Santosh V M Aug 19 '10 at 09:38
  • 1
    Consider also [this answer](http://stackoverflow.com/a/6172281/474189) from a related question, which shows another alternative. – Duncan Jones May 15 '14 at 12:44
  • 1
    FYI Since Java 1.4, it is no longer required and recommended that you utilise the `Document` for this functionality, instead use a `DocumentFilter`, see [Implementing a Document Filter](http://docs.oracle.com/javase/tutorial/uiswing/components/generaltext.html#filter) and [DocumentFilter Examples](http://www.jroller.com/dpmihai/entry/documentfilter) for more details – MadProgrammer Jan 27 '16 at 22:10
  • Horribly long answer as compared to @Adham Gamal's answer – Dia Sheikh Feb 10 '21 at 12:37
9

If you wanna have everything into one only piece of code, then you can mix tim's answer with the example's approach found on the API for JTextField, and you'll get something like this:

public class JTextFieldLimit extends JTextField {
    private int limit;

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

    @Override
    protected Document createDefaultModel() {
        return new LimitDocument();
    }

    private class LimitDocument extends PlainDocument {

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

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

    }

}

Then there is no need to add a Document to the JTextFieldLimit due to JTextFieldLimit already have the functionality inside.

  • 1
    FYI Since Java 1.4, it is no longer required and recommended that you utilise the `Document` for this functionality, instead use a `DocumentFilter`, see [Implementing a Document Filter](http://docs.oracle.com/javase/tutorial/uiswing/components/generaltext.html#filter) and [DocumentFilter Examples](http://www.jroller.com/dpmihai/entry/documentfilter) for more details – MadProgrammer Jan 27 '16 at 22:11
8

Read the section from the Swing tutorial on Implementing a DocumentFilter for a more current solution.

This solution will work an any Document, not just a PlainDocument.

This is a more current solution than the one accepted.

camickr
  • 321,443
  • 19
  • 166
  • 288
8

Great question, and it's odd that the Swing toolkit doesn't include this functionality natively for JTextFields. But, here's a great answer from my Udemy.com course "Learn Java Like a Kid":

txtGuess = new JTextField();
txtGuess.addKeyListener(new KeyAdapter() {
    public void keyTyped(KeyEvent e) { 
        if (txtGuess.getText().length() >= 3 ) // limit textfield to 3 characters
            e.consume(); 
    }  
});

This limits the number of characters in a guessing game text field to 3 characters, by overriding the keyTyped event and checking to see if the textfield already has 3 characters - if so, you're "consuming" the key event (e) so that it doesn't get processed like normal.

  • 5
    This would also block backspace or delete key events, so once you reach the 3 chars, you can no longer remove them. – Marco Apr 18 '19 at 17:32
5

Just Try This :

textfield.addKeyListener(new java.awt.event.KeyAdapter() {
    public void keyTyped(java.awt.event.KeyEvent evt) {
        if(textfield.getText().length()>=5&&!(evt.getKeyChar()==KeyEvent.VK_DELETE||evt.getKeyChar()==KeyEvent.VK_BACK_SPACE)) {
            getToolkit().beep();
            evt.consume();
         }
     }
});
Adham Gamal
  • 775
  • 8
  • 13
  • 2
    FYI Since Java 1.4, it is no longer required and recommended that you utilise the `Document` for this functionality, instead use a `DocumentFilter`, see [Implementing a Document Filter](http://docs.oracle.com/javase/tutorial/uiswing/components/generaltext.html#filter) and [DocumentFilter Examples](http://www.jroller.com/dpmihai/entry/documentfilter) for more details, `KeyListener` is never a good idea with text components – MadProgrammer Jan 27 '16 at 22:11
  • 1
    Works like charm! Thanks. There're at least 3 answers to this question that are a copy of this answer. Isn't there any control on plagiarism on SO? If an answer already exists, why add the same answer as a new one?? – Dia Sheikh Feb 10 '21 at 12:39
3

I have solved this problem by using the following code segment:

private void jTextField1KeyTyped(java.awt.event.KeyEvent evt) {
    boolean max = jTextField1.getText().length() > 4;
    if ( max ){
        evt.consume();
    }        
}
CosmicGiant
  • 6,275
  • 5
  • 43
  • 58
1
import java.awt.KeyboardFocusManager;
import javax.swing.InputVerifier;
import javax.swing.JTextField;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.DocumentFilter.FilterBypass;

/**
 *
 * @author Igor
 */
public class CustomLengthTextField extends JTextField {

    protected boolean upper = false;
    protected int maxlength = 0;

    public CustomLengthTextField() {
        this(-1);
    }

    public CustomLengthTextField(int length, boolean upper) {
        this(length, upper, null);
    }

    public CustomLengthTextField(int length, InputVerifier inpVer) {
        this(length, false, inpVer);
    }

    /**
     *
     * @param length - maksimalan length
     * @param upper - turn it to upercase
     * @param inpVer - InputVerifier
     */
    public CustomLengthTextField(int length, boolean upper, InputVerifier inpVer) {
        super();
        this.maxlength = length;
        this.upper = upper;
        if (length > 0) {
            AbstractDocument doc = (AbstractDocument) getDocument();
            doc.setDocumentFilter(new DocumentSizeFilter());
        }
        setInputVerifier(inpVer);
    }

    public CustomLengthTextField(int length) {
        this(length, false);
    }

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

    class DocumentSizeFilter extends DocumentFilter {

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

            //This rejects the entire insertion if it would make
            //the contents too long. Another option would be
            //to truncate the inserted string so the contents
            //would be exactly maxCharacters in length.
            if ((fb.getDocument().getLength() + str.length()) <= maxlength) {
                super.insertString(fb, offs, str, a);
            }
        }

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

            if (upper) {
                str = str.toUpperCase();
            }

            //This rejects the entire replacement if it would make
            //the contents too long. Another option would be
            //to truncate the replacement string so the contents
            //would be exactly maxCharacters in length.
            int charLength = fb.getDocument().getLength() + str.length() - length;

            if (charLength <= maxlength) {
                super.replace(fb, offs, length, str, a);
                if (charLength == maxlength) {
                    focusNextComponent();
                }
            } else {
                focusNextComponent();
            }
        }

        private void focusNextComponent() {
            if (CustomLengthTextField.this == KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner()) {
                KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent();
            }
        }
    }
}
Igor Vuković
  • 742
  • 12
  • 25
0

Just put this code in KeyTyped event:

    if ((jtextField.getText() + evt.getKeyChar()).length() > 20) {
        evt.consume();
    }

Where "20" is the maximum number of characters that you want.