java JTextField 限制字符数量输入并仅接受数字
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12793030/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JTextField limiting character amount input and accepting numeric only
提问by Weddy
here's the code that i have on how to limit the character input length
这是我关于如何限制字符输入长度的代码
class JTextFieldLimit extends PlainDocument {
private int limit;
// optional uppercase conversion
private boolean toUppercase = false;
JTextFieldLimit(int limit) {
super();
this.limit = limit;
}
JTextFieldLimit(int limit, boolean upper) {
super();
this.limit = limit;
toUppercase = upper;
}
@Override
public void insertString
(int offset, String str, AttributeSet attr)
throws BadLocationException {
if (str == null) return;
if ((getLength() + str.length()) <= limit) {
if (toUppercase) str = str.toUpperCase();
super.insertString(offset, str, attr);
}
}
}
can be implemented by txtSample.setDocument(new JTextFieldLimit(30));
可以通过 txtSample.setDocument(new JTextFieldLimit(30));
and here's what i have on accepting numeric numbers only(it accepts decimal though w/c i dont need)
这是我只接受数字的内容(它接受十进制,尽管 w/ci 不需要)
class NumericDocument extends PlainDocument {
protected int decimalPrecision = 0;
protected boolean allowNegative = false;
public NumericDocument(int decimalPrecision, boolean allowNegative) {
super();
this.decimalPrecision = decimalPrecision;
this.allowNegative = allowNegative;
}
@Override
public void insertString(int offset, String str, AttributeSet attr) throws BadLocationException {
if (str != null){
if (StringFormat.isNumeric(str) == false && str.equals(".") == false && str.equals("-") == false){ //First, is it a valid character?
Toolkit.getDefaultToolkit().beep();
return;
}
else if (str.equals(".") == true && super.getText(0, super.getLength()).contains(".") == true){ //Next, can we place a decimal here?
Toolkit.getDefaultToolkit().beep();
return;
}
else if (StringFormat.isNumeric(str) == true && super.getText(0, super.getLength()).indexOf(",") != -1 && offset>super.getText(0, super.getLength()).indexOf(",") && super.getLength()-super.getText(0, super.getLength()).indexOf(".")>decimalPrecision && decimalPrecision > 0){ //Next, do we get past the decimal precision limit?
Toolkit.getDefaultToolkit().beep();
return;
}
else if (str.equals("-") == true && (offset != 0 || allowNegative == false)){ //Next, can we put a negative sign?
Toolkit.getDefaultToolkit().beep();
return;
}
super.insertString(offset, str, attr);
}
return;
}
public static class StringFormat
{
public StringFormat()
{
}
public static 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;
}
}
}
}
and heres how to use this code: txtSample.setDocument(new NumericDocument(0,false));
以及如何使用此代码: txtSample.setDocument(new NumericDocument(0,false));
now the problem is the txtSample
can only setDocument
once. How do i limit a jtextfield length and accept numbers only at the same time? Or is there any simpler way to do this? Thanks. :D
现在的问题是txtSample
只能setDocument
一次。如何限制 jtextfield 长度并同时仅接受数字?或者有没有更简单的方法来做到这一点?谢谢。:D
回答by MadProgrammer
You're on the right track, except you will want to use a DocumentFilterinstead of implementing your own document.
您走在正确的轨道上,除了您想要使用DocumentFilter而不是实现您自己的文档。
MDP's Webloghas a number of excellent examples (including limiting the length and character type).
MDP 的 Weblog有很多很好的例子(包括限制长度和字符类型)。
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<DocumentFilter> filters;
private AttributeSet attr;
public ChainableFilter() {
filters = new ArrayList<DocumentFilter>(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
.
您所做的工作与DocumentFilters
工作方式之间的基本概念几乎相同。好处是,您不会将自己限制在 a 上PlainDocument
,理论上您可以将其应用于 aJTextPane
或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 ;)
同样,我知道它可以编译,但我没有测试过它(特别是数字过滤器),但这将是一个很好的调试练习;)
回答by gmatagmis
JTextComponent txt = new JFormattedTextField( new LimitedIntegerFormatter(limit) );
txt.addPropertyChangeListener("value", yourPropertyChangeListener);
import javax.swing.text.DefaultFormatter;
import java.text.ParseException;
public class LimitedIntegerFormatter extends DefaultFormatter {
static final long serialVersionUID = 1l;
private int limit;
public LimitedIntegerFormatter( int limit ) {
this.limit = limit;
setValueClass(Integer.class);
setAllowsInvalid(false);
setCommitsOnValidEdit(true);
}
@Override
public Object stringToValue(String string) throws ParseException {
if (string.equals("")) return null;
if (string.length() > limit) throw new ParseException(string, limit);
return super.stringToValue(string);
}
}
yourPropertyChangeListener will be called with
yourPropertyChangeListener 将被调用
new PropertyChangeEvent( "value", Integer oldValue, Integer newValue )
new PropertyChangeEvent( "value", Integer oldValue, Integer newValue )
( oldValue or newValue will be null in "" text case )
( oldValue 或 newValue 在 "" 文本情况下将为 null )
after every valid edit
每次有效编辑后
回答by pixylife
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JTextField;
public class Validation {
public static void validateInt(final JTextField txt){
txt.addKeyListener(new KeyAdapter() {
@Override
public void keyTyped(KeyEvent e) {
char c = e.getKeyChar();
if ( ((c < '0') || (c > '9'))
&& (c != KeyEvent.VK_BACK_SPACE)) {
e.consume(); // ignore event
}
}
});
}
public static void validatelength(final JTextField txt,final int size){
txt.addKeyListener(new KeyAdapter() {
@Override
public void keyTyped(KeyEvent e) {
String text = txt.getText();
int length = text.length();
if (length == size) {
e.consume();// ignore event
}
}
});
}
}
回答by pixylife
public static boolean validateInt(String txt) {
String regx = "^[(0-9),;]+$";
Pattern pattern = Pattern.compile(regx, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(txt);
boolean b = matcher.find();
return b;
}
回答by Tommy Olsen
I'm currently working on a small project with a Sudoku-solver. I limited my inputs to only numbers by checking wether the input was in an string array with the numbers. I wrote it directly in the JTextFieldLimit.
我目前正在使用数独求解器进行一个小项目。我通过检查输入是否在带有数字的字符串数组中,将我的输入限制为仅数字。我直接在 JTextFieldLimit 中写的。
class JTextFieldLimit extends PlainDocument {
private int limit;
//Added the following 2 lines
String[] numbers = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
boolean isAccepted = false;
//
JTextFieldLimit(int limit) {
super();
this.limit = limit;
}
public void insertString(int offset, String str, AttributeSet attr) throws BadLocationException {
if (str == null)
return;
//And the following 2 lines
for (String thisnumber : numbers) {
isAccepted = str.equals(thisnumber);
if (isAccepted) {
//
if ((getLength() + str.length()) <= limit) {
super.insertString(offset, str, attr);
}
}
}
}
}
回答by Igor Vukovi?
import java.awt.Component;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.DocumentFilter;
import javax.swing.text.JTextComponent;
import org.apache.commons.lang.StringUtils;
public class NumberTextField extends JTextField {
protected int maxlength = 0;
public NumberTextField() {
this(10);
}
public NumberTextField(int length) {
super();
this.maxlength = length;
initializeForNumbers();
}
public void setMaxLength(int length) {
this.maxlength = length;
}
protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_ENTER || keyCode == KeyEvent.VK_ESCAPE) {
return false;
}
return super.processKeyBinding(ks, e, condition, pressed);
}
private void initializeForNumbers() {
Document document = getDocument();
if (document != null) {
((AbstractDocument) document).setDocumentFilter(new DocumentHandler());
}
}
private class DocumentHandler extends DocumentFilter {
public void insertString(DocumentFilter.FilterBypass fb,
int offset, String string, AttributeSet attr)
throws BadLocationException {
if (string == null) {
return;
} else {
replace(fb, offset, 0, string, attr);
}
}
public void remove(DocumentFilter.FilterBypass fb,
int offset, int length)
throws BadLocationException {
replace(fb, offset, length, "", null);
}
public void replace(final DocumentFilter.FilterBypass fb,
int offset, int length, String text, AttributeSet attrs)
throws BadLocationException {
Document doc = fb.getDocument();
int currentLength = doc.getLength();
String currentContent = doc.getText(0, currentLength);
String before = currentContent.substring(0, offset);
String after = currentContent.substring(length + offset, currentLength);
String newValue = before + (text == null ? "" : text) + after;
if (newValue.length() > maxlength) {
return;
} else {
checkInput(newValue, offset);
fb.replace(offset, length, text, attrs);
if (doc.getLength() >= maxlength) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Component c = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
if (c != null && c instanceof JTextComponent) {
JTextComponent component = (JTextComponent) c;
Document compDoc = component.getDocument();
if (compDoc.equals(fb.getDocument())) {
KeyboardFocusManager.getCurrentKeyboardFocusManager().focusNextComponent();
}
}
}
});
return;
}
}
}
private void checkInput(String proposedValue, int offset)
throws BadLocationException {
if (proposedValue.length() > 0 && !StringUtils.isNumeric(proposedValue)) {
throw new BadLocationException(
proposedValue, offset);
}
}
}
}
回答by itro
yourJTextField.addKeyListener(new KeyAdapter()
{
@Override
public void keyTyped(KeyEvent e)
{
// Here limiting the character of your number. for examlpe this wil only accept one digit
if (yourJTextField.getText().length() == 1) {
e.consume();
}
// Here limiting your input to only number
char c = e.getKeyChar();
if(!((c >= '0') && (c <= '7') || (c == KeyEvent.VK_BACK_SPACE) || (c == KeyEvent.VK_DELETE)))
{
//do what so ever you want
}
else
{
//do what so ever you want
}
}
})