2

我需要一个只接受正整数作为输入的 JTextField。我的实现大部分都有效。当您在字段中键入文本时,会出现数字,而不会出现非数字。

但是构造函数的“文本”参数存在问题。如果我传递一个包含正整数的字符串表示形式的字符串,我希望文本字段开始时包含该字段,但文本字段开始时为空白。例如,这样做会导致它出现我所描述的症状: new NumericTextField("1", 5);

在初始化期间不调用重写的 insertString 方法。

我做错了什么,我该如何解决?这是代码...

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


/**
  * A JTextField that only accepts characters that are digits. Also, the first character can't be "0".
 */
public class NumericTextField extends JTextField {

    public class CustomFilterDocument extends PlainDocument {
        public void insertString(int offset, String text, AttributeSet aset) throws BadLocationException {
            if (isLegalValue(text)) {
                super.insertString(offset, text, aset);
            }
        }
    }

    private static boolean isLegalValue(String text) {
        if (text == null) {
            return false;
        }

        int len = text.length();
        for (int i = 0; i < len; i++) {
            char c = text.charAt(i);
            if (!Character.isDigit(c) || (i ==0 && c == '0')) {
                return false;
            }
        }

        return true;
    }

    public NumericTextField() {
        super();
        setDocument(new CustomFilterDocument());
    }

    public NumericTextField(int columns) {
        super(columns);
        setDocument(new CustomFilterDocument());
    }

    public NumericTextField(String text) {
        super(text);
        setDocument(new CustomFilterDocument());
    }

    public NumericTextField(String text, int columns) {
        super(text, columns);
        setDocument(new CustomFilterDocument());
    }
}

固定版本(使用我从回复中学到的)如下所示:

public NumericTextField(String text) {
    super(text);
    initText(text);
}

public NumericTextField(String text, int columns) {
    super(text, columns);
    initText(text);
}

private void initText(String text) {
    Document doc = new CustomFilterDocument();
    try {
        doc.insertString(0, text, null);
    } catch (BadLocationException ble) {
    }
    setDocument(doc);
}
4

3 回答 3

1

问题是您将文档设置为新文档。这将删除您通过构造函数传入的任何内容。

public NumericTextField(String text) {
    super(text);
    // This next line will erase the content on the current document
    setDocument(new CustomFilterDocument());
}
于 2010-09-07T23:58:08.337 回答
0

在使用现有模型构建时,许多 Swing 组件并不是特别聪明,这与整个模型理念相悖。

通常你不需要子类化JTextField(事实上,如果你使用DocumentFilter你也不需要子类Document化)。将文本插入文档,创建文本字段,然后将文档设置到文本字段中。那里没有太多的开销。

如果你真的想要,你可以JTextField继承这个奇怪命名的createDefaultModel. 如果您需要一些上下文变量,则不能通过构造函数传递它们,因为在调用此方法时它还没有完成执行(实际上,不要触摸this)。但是,如果它是匿名内部类(并使用-target 1.4或更高版本编译),那么您可以访问final封闭方法的本地字段。

于 2010-09-08T00:10:53.497 回答
0

JFormattedTextField

 JTextComponent txt = new JFormattedTextField( new PositiveIntegerFormatter() );
 txt.addPropertyChangeListener("value", yourPropertyChangeListener);


import javax.swing.text.DefaultFormatter;
import java.text.ParseException;

public class PositiveIntegerFormatter extends DefaultFormatter {

  static final long serialVersionUID = 1l;

  public PositiveIntegerFormatter() {
    setValueClass(Integer.class);
    setAllowsInvalid(false);
    setCommitsOnValidEdit(true);
  }
  @Override
  public Object stringToValue(String string) throws ParseException {
    if (string.equals("")) return null;
    Integer value = (Integer)super.stringToValue(string);
    if ( Integer.signum(value.intValue()) < 0 ) throw new ParseException(string, 0);
    return value;
  }
}

yourPropertyChangeListener 将被调用

新的 PropertyChangeEvent(“值”,整数 oldValue,整数 newValue)

( oldValue 或 newValue 在 "" 文本案例中将为空)

每次有效编辑后

笔记。id 不支持您正在使用的构造函数。要设置文本和大小,您应该添加

  txt.setText( String text );
  txt.setPreferredSize( int x, int y );
于 2012-11-16T11:26:19.300 回答