问题子类化JTextField:不显示初始文本值

时间:2010-09-07 23:55:00

标签: java swing jtextfield

我需要一个只接受正整数作为输入的JTextField。我的实施大多有效。当您在字段中键入文本时,会显示数字,并且不会显示非数字。

但是构造函数的“text”参数存在问题。如果我传递一个包含正整数的String表示的String,我希望文本字段开始包含该字段,而是文本字段开始为空。例如,这样做会导致它出现我所描述的症状: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);
}

3 个答案:

答案 0 :(得分:1)

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

public NumericTextField(String text) {
    super(text);
    // This next line will erase the content on the current document
    setDocument(new CustomFilterDocument());
}

答案 1 :(得分:0)

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

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

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

答案 2 :(得分: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

new PropertyChangeEvent(“value”,Integer oldValue,Integer newValue)

(oldValue或newValue在“”文本案例中)为空

每次有效编辑后

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

  txt.setText( String text );
  txt.setPreferredSize( int x, int y );