如何限制JTextField中的字符数量?

33

如何限制用户在JTextField中输入的字符数?

假设我想最多输入5个字符,之后将无法再输入。


3
虽然使用自定义文档可以起作用,但解决此问题的首选方法是使用JFormattedTextField或使用DocumentFilter。我相信这些都是在JDK 1.3版本中添加的功能。Swing教程涵盖了这两种方法(甚至从教程中删除了自定义文档方法)。 - camickr
自Java 1.4以来,不再需要或建议您使用Document来实现此功能,而是使用DocumentFilter,请参见实现文档过滤器DocumentFilter示例获取更多详细信息。 - MadProgrammer
8个回答

43

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

然后

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));
     }
}
(来自谷歌的第一个结果)

2
是否没有像textfield.maximumlimit(10);这样的直接函数? - Santosh V M
当我输入上述代码时,我遇到了两个错误。 1 - 包com.sun.java.swing.text不存在 2 - 找不到符号PlainDocument - Santosh V M
1
请考虑查看相关问题中的此答案,它展示了另一种选择。 - Duncan Jones
1
自Java 1.4以来,不再需要或建议您使用Document来实现此功能,而是使用DocumentFilter,请参见实现文档过滤器DocumentFilter示例获取更多详细信息。 - MadProgrammer
与@Adham Gamal的答案相比,这个答案非常冗长。 - Noor ul Ain
显示剩余3条评论

9
如果您想将所有内容合并到一个代码块中,那么您可以将Tim的答案与API中找到的示例方法相结合,如JTextField所述,您将得到以下内容:
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);
            }
        }       

    }

}

由于JTextFieldLimit已经具备了所需的功能,因此无需将文档添加到JTextFieldLimit中。


1
自Java 1.4以来,不再需要或建议您使用Document来实现此功能,而是使用DocumentFilter,请参见实现文档过滤器DocumentFilter示例获取更多详细信息。 - MadProgrammer

8

非常好的问题,很奇怪Swing工具包没有为JTextFields本地包含此功能。但是,在我的Udemy.com课程“像孩子一样学习Java”中,这里有一个很好的答案:

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

这将限制猜数字游戏文本字段中的字符数为3个字符,通过覆盖keyTyped事件并检查文本字段是否已经有3个字符-如果是,则“使用”键事件(e),使其不像正常情况下那样被处理。


5
这也会阻止退格键或删除键的事件,因此一旦您达到3个字符,就无法再将它们删除。 - Marco

8

请阅读 Swing 教程中关于 实现 DocumentFilter 的部分,以获得更加现代的解决方案。

这个解决方案适用于任何 Document,而不仅仅是 PlainDocument。

这是比原先被接受的方案更为现代的解决方案。


5

试一试这个:

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

2
自Java 1.4以来,不再需要或建议您使用Document来实现此功能,而是使用DocumentFilter,请参见实现文档过滤器DocumentFilter示例获取更多详细信息。在文本组件中,KeyListener永远不是一个好主意。 - MadProgrammer
1
运行得非常顺利!谢谢。至少有三个回答复制了这个答案,SO上难道没有防抄袭的措施吗?如果已经存在一个答案,为什么还要重复发表相同的答案呢? - Noor ul Ain

3
我已经通过使用以下代码段解决了这个问题:
private void jTextField1KeyTyped(java.awt.event.KeyEvent evt) {
    boolean max = jTextField1.getText().length() > 4;
    if ( max ){
        evt.consume();
    }        
}

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

0

只需将此代码放入KeyTyped事件中:

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

其中“20”是您想要的最大字符数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接