30

I want to set the maximum length of a JTextField, so that you can't enter more characters than the limit. This is the code I have so far...

    textField = new JTextField();
    textField.setBounds(40, 39, 105, 20);
    contentPane.add(textField);
    textField.setColumns(10);

Is there any simple way to put a limit on the number of characters?

wattostudios
  • 8,666
  • 13
  • 43
  • 57
  • 2
    don't use setBounds, ever. Instead use a LayoutManager (in the field's parent) which locates/sizes the component as required. – kleopatra Apr 13 '12 at 10:20
  • 1
    As of Java 1.4 the recommended method for achieving this kind of result is to use a `DocumentFilter`, all other solutions are either "hacks" or "work arounds" designed before the `DocumentFilter` was available and should, for the most part, be ignored – MadProgrammer Dec 13 '14 at 12:13

9 Answers9

30

You can do something like this (taken from here):

import java.awt.FlowLayout;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

class JTextFieldLimit extends PlainDocument {
  private int limit;
  JTextFieldLimit(int limit) {
    super();
    this.limit = limit;
  }

  JTextFieldLimit(int limit, boolean upper) {
    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);
    }
  }
}

public class Main extends JFrame {
  JTextField textfield1;

  JLabel label1;

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

    setSize(300,300);
    setVisible(true);
  }
}

Edit: Take a look at this previous SO post. You could intercept key press events and add/ignore them according to the current amount of characters in the textfield.

Community
  • 1
  • 1
npinti
  • 51,780
  • 5
  • 72
  • 96
  • 1
    Isn't there a easier way which we can choose from JFrame. –  Apr 13 '12 at 07:39
  • -1 for the edit: intercepting key events (aka: using a keyListener) is **not** the way to go .. – kleopatra Apr 13 '12 at 10:18
  • @kleopatra: Can you please suggest another method? – npinti Apr 13 '12 at 10:21
  • 3
    why do you require another solution? the original one is the way to go. it is easy, readable and reusable for every new textfield. when intercepting key events, you could still paste a very long text into the field, bypassing the character limit – moeTi Apr 13 '12 at 10:45
  • 2
    There is no longer any need to override or extend from `Document` to achieve this, the `DocumentFilter` API (since Java 1.4) has superseded this and almost all other "work arounds" or "hacks" that were done in Java 1.3 – MadProgrammer Dec 13 '14 at 12:11
  • 1
    A better solution is to use JFormattedTextField with MaskFormatter. `MaskFormatter mask = new MaskFormatter("*****");` `JFormattedTextField textField new JFormattedTextField(mask)` – Ould Abba Mar 14 '16 at 13:08
  • There will be so much problem if you are using key event to handle this thing. I tried that. – panoet Sep 15 '16 at 22:11
25

Since the introduction of the DocumentFilter in Java 1.4, the need to override Document has been lessoned.

DocumentFilter provides the means for filtering content been passed to the Document before it actually reaches it.

These allows the field to continue to maintain what ever document it needs, while providing the means to filter the input from the user.

import java.awt.EventQueue;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;

public class LimitTextField {

    public static void main(String[] args) {
        new LimitTextField();
    }

    public LimitTextField() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JTextField pfPassword = new JTextField(20);
                ((AbstractDocument)pfPassword.getDocument()).setDocumentFilter(new LimitDocumentFilter(15));

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridBagLayout());
                frame.add(pfPassword);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class LimitDocumentFilter extends DocumentFilter {

        private int limit;

        public LimitDocumentFilter(int limit) {
            if (limit <= 0) {
                throw new IllegalArgumentException("Limit can not be <= 0");
            }
            this.limit = limit;
        }

        @Override
        public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
            int currentLength = fb.getDocument().getLength();
            int overLimit = (currentLength + text.length()) - limit - length;
            if (overLimit > 0) {
                text = text.substring(0, text.length() - overLimit);
            }
            if (text.length() > 0) {
                super.replace(fb, offset, length, text, attrs); 
            }
        }

    }

}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • nice solution. Document filter is the correct approach there is no need for extending Document – Acewin Jan 23 '15 at 20:00
  • Why override `replace` instead of `insertString`? Does it work on both inserting and replacing of text? – Gustavo Feb 05 '16 at 14:00
  • @Gustavo Not really, generally `replace` is called almost all the time, infact, you could just make `insertString` call `replace` for the few times it's called. Add some debug statements in and have a look – MadProgrammer Feb 05 '16 at 20:17
  • @MadProgrammer could you explain why you need the `text.length() > 0` check? Turns out that a bug in my application whereby a text field was not being cleared when invoking`setText("")` on it, is due to this check preventing the `super.replace()` from being called. Taking the check out doesn't appear to have any negative side-effects! – Matthew Wise Sep 14 '16 at 08:53
  • @MatthewWise It's mostly there to see if there is actually something worth doing. If it has no ill effects from your perspective, then I'd leave it out – MadProgrammer Sep 14 '16 at 08:58
  • 4
    @MadProgrammer I ran into the same problem and corrected it by replacing the condition with: `text.length() > 0 || length > 0`. That way it checks for text either being inserted or deleted (which is what happens when you clear a field). – Bruce Feist Apr 18 '17 at 00:26
  • Control block `if (text.length() > 0)` is wrong when you send empty string to **setText("")** function. for that you need to control like `if (text.length() >= 0)` . Also null String object raises _exception_. For that you need to check it as well. You are welcome. – fatih May 07 '18 at 10:59
  • 1
    @fatih `if (text.length() >= 0)` will be always true, an string length can't be negative. – PhoneixS May 23 '19 at 12:01
4

It's weird that the Swing toolkit doesn't include this functionality, but here's the best answer to your question:

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

I use this in a fun guessing game example in my Udemy.com course "Learn Java Like a Kid". Cheers - Bryson

  • 2
    *"It's weird that the Swing toolkit doesn't include this functionality"* - It's called a `DocumentFilter` – MadProgrammer Sep 10 '16 at 01:32
  • 1
    I believe Dr. Payne meant it's weird Swing doesn't include this functionality as a property of JTextField, seen it's such a commonly required feature – Mishax Sep 19 '17 at 08:15
  • 2
    This will not prevent pasting of content that has more than 3 characters – felvhage Jun 28 '18 at 15:36
0
private void jTextField1KeyPressed(java.awt.event.KeyEvent evt)
{
    if(jTextField1.getText().length()>=5)
    {
        jTextField1.setText(jTextField1.getText().substring(0, 4));
    }
}

I have taken a jtextfield whose name is jTextField1, the code is in its key pressed event. I Have tested it and it works. And I am using the NetBeans IDE.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
  • 2
    no - a keyListener is _not_ an option to validate input (f.i. limit the number of chars) – kleopatra Jan 29 '13 at 16:04
  • Why so many downvotes? I found it a smart way of achieving the goal. +1 – h2O Jan 25 '14 at 11:44
  • 4
    @h2O Because it's a bad idea. This approach doesn't into account what might happen if the user pastes text into the field and may not be notified on some platforms... – MadProgrammer Jun 29 '14 at 03:44
0

private void validateInput() {

      if (filenametextfield.getText().length() <= 3 )
        {

          errorMsg2.setForeground(Color.RED);

        }
        else if(filenametextfield.getText().length() >= 3 && filenametextfield.getText().length()<= 25)
        {

             errorMsg2.setForeground(frame.getBackground());
             errorMsg.setForeground(frame2.getBackground());

        } 
        else if(filenametextfield.getText().length() >= 25)
        {

             remove(errorMsg2);
             errorMsg.setForeground(Color.RED);
             filenametextfield.addKeyListener(new KeyAdapter() {
                  public void keyTyped(KeyEvent e) {
                     if(filenametextfield.getText().length()>=25)
                        {
                         e.consume();
                         e.getModifiers();

                        }
                 }
            });
        }


    }
  • The above code makes the user to enter characters which should be > 3 and also < 25 .The code also helps the user to edit and re-enter the characters,which most of the solutions provided wont allow. – jinuprakash Apr 16 '20 at 08:01
0

Here is another way to Limit the length as below.

label_4_textField.addKeyListener(new KeyListener() {
            
    @Override
    public void keyTyped(KeyEvent arg0) {
        if(label_4_textField.getText().length()>=4) // Limit to 4 characters
        {
            label_4_textField.setText(label_4_textField.getText().substring(0,3));
        }
    }
});
nkrivenko
  • 1,231
  • 3
  • 14
  • 23
-1

private void jTextField1KeyTyped(java.awt.event.KeyEvent evt) {                                   
if (jTextField1.getText().length()>=3) {
            getToolkit().beep();
            evt.consume();
        }
    }
ryo
  • 9
-1
public void Letters(JTextField a) {
    a.addKeyListener(new KeyAdapter() {
        @Override
        public void keyTyped(java.awt.event.KeyEvent e) {
            char c = e.getKeyChar();
            if (Character.isDigit(c)) {
                e.consume();
            }
            if (Character.isLetter(c)) {
                e.setKeyChar(Character.toUpperCase(c));
            }
        }
    });
}

public void Numbers(JTextField a) {
    a.addKeyListener(new KeyAdapter() {
        @Override
        public void keyTyped(java.awt.event.KeyEvent e) {
            char c = e.getKeyChar();
            if (!Character.isDigit(c)) {
                e.consume();
            }
        }
    });
}

public void Caracters(final JTextField a, final int lim) {
    a.addKeyListener(new KeyAdapter() {
        @Override
        public void keyTyped(java.awt.event.KeyEvent ke) {
            if (a.getText().length() == lim) {
                ke.consume();
            }
        }
    });
}
Andres
  • 7
  • 1
-1

Here is an optimized version of npinti's answer:

import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
import javax.swing.text.PlainDocument;
import java.awt.*;

public class TextComponentLimit extends PlainDocument
{
    private int charactersLimit;

    private TextComponentLimit(int charactersLimit)
    {
        this.charactersLimit = charactersLimit;
    }

    @Override
    public void insertString(int offset, String input, AttributeSet attributeSet) throws BadLocationException
    {
        if (isAllowed(input))
        {
            super.insertString(offset, input, attributeSet);
        } else
        {
            Toolkit.getDefaultToolkit().beep();
        }
    }

    private boolean isAllowed(String string)
    {
        return (getLength() + string.length()) <= charactersLimit;
    }

    public static void addTo(JTextComponent textComponent, int charactersLimit)
    {
        TextComponentLimit textFieldLimit = new TextComponentLimit(charactersLimit);
        textComponent.setDocument(textFieldLimit);
    }
}

To add a limit to your JTextComponent, simply write the following line of code:

JTextFieldLimit.addTo(myTextField, myMaximumLength);
Community
  • 1
  • 1
BullyWiiPlaza
  • 17,329
  • 10
  • 113
  • 185