【问题标题】:problem subclassing JTextField: initial text value is not displayed问题子类化 JTextField:不显示初始文本值
【发布时间】:2010-09-07 23:55:00
【问题描述】:

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

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

【问题讨论】:

    标签: java swing jtextfield


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          猜你喜欢
          • 2017-05-07
          • 1970-01-01
          • 2020-10-17
          • 1970-01-01
          • 2021-12-24
          • 2020-10-14
          • 1970-01-01
          • 2019-11-27
          • 2017-08-20
          相关资源
          最近更新 更多