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 が呼び出されます

new PropertyChangeEvent( "値", Integer oldValue, Integer newValue )

( "" テキストの場合、 oldValue または newValue は null になります)

有効な編集ごとに

ノート。id は、使用しているコンストラクターをサポートしていません。テキストとサイズを設定するには、追加する必要があります

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