Java 通往'的更清洁的道路;消毒';JTextField输入?

Java 通往'的更清洁的道路;消毒';JTextField输入?,java,swing,jtextfield,formatted-input,Java,Swing,Jtextfield,Formatted Input,因此,我正在为一个JTextField编写TextValueChanged处理程序,该处理程序的输入耗时很长。它只需要允许用户键入介于0和Long.MAX之间的有效值。如果用户键入无效字符,则应将其删除,以便JTextField中的值始终为有效长字符 我当前的代码看起来像这样,但看起来很难看。在没有外部lib(包括apachecommons)的情况下,有没有更干净/更简单的方法来实现这一点 public void textValueChanged(TextEvent e) { if (e

因此,我正在为一个JTextField编写TextValueChanged处理程序,该处理程序的输入耗时很长。它只需要允许用户键入介于0和Long.MAX之间的有效值。如果用户键入无效字符,则应将其删除,以便JTextField中的值始终为有效长字符

我当前的代码看起来像这样,但看起来很难看。在没有外部lib(包括apachecommons)的情况下,有没有更干净/更简单的方法来实现这一点

public void textValueChanged(TextEvent e) {
    if (e.getSource() instanceof JTextField) {
        String text = ((JTextField) e.getSource()).getText();
        try {
            // Try to parse cleanly
            long longNum = Long.parseLong(text);
            // Check for < 1 
            if (longNum < 1) throw new NumberFormatException();
            // If we pass, set the value and return
            setOption("FIELDKEY", longNum);
        } catch (NumberFormatException e1) {
            // We failed, so there's either a non-numeric or it's too large.
            String s = ((JTextField) e.getSource()).getText();
            // Strip non-numeric characters
            s = s.replaceAll("[^\\d]", "");
            long longNum = -1;
            if (s.length() != 0) {
                /* Really ugly workaround for the fact that a
                 * TextValueChanged event can capture more than one
                 * keystroke at a time, if it's typed fast enough,
                 * so we might have to strip more than one
                 * character. */
                Exception e3;
                do {
                    e3 = null;
                    try {
                        // Try and parse again
                        longNum = Long.parseLong(s);
                    } catch (NumberFormatException e2) {
                        // We failed, so it's too large.
                        e3 = e2;
                        // Strip the last character and try again.
                        s = s.substring(0, s.length() - 1);
                    }
                    // Repeat
                } while (e3 != null);
            }
            // We parsed, so add it (or blank it if it's < 1) and return.
            setOption("FIELDKEY", (longNum < 1 ? 0 : longNum));
        }
    }
}
public void textValueChanged(TextEvent e){
if(例如,getSource()实例为JTextField){
字符串文本=((JTextField)e.getSource()).getText();
试一试{
//尝试清晰地解析
long longNum=long.parseLong(文本);
//检查是否小于1
如果(longNum<1)抛出新的NumberFormatException();
//如果通过,则设置值并返回
设置选项(“字段键”,longNum);
}捕获(NumberFormatException e1){
//我们失败了,所以要么是非数字的,要么太大了。
字符串s=((JTextField)e.getSource()).getText();
//带非数字字符
s=s.replaceAll(“[^\\d]”,即“);
long longNum=-1;
如果(s.长度()!=0){
/*真是难看的解决办法,因为
*TextValueChanged事件可以捕获多个
*一次击键,如果输入速度足够快,
*所以我们可能要剥掉不止一个
*性格*/
例外e3;
做{
e3=零;
试一试{
//请再次尝试分析
longNum=Long.parseLong(s);
}捕获(NumberFormatException e2){
//我们失败了,所以它太大了。
e3=e2;
//删除最后一个字符,然后重试。
s=s.substring(0,s.length()-1);
}
//重复
}而(e3!=null);
}
//我们解析了它,所以添加它(如果小于1,则为空)并返回。
设置选项(“字段键”(longNum<1?0:longNum));
}
}
}

从getOption(键)调用中不断重新填充该字段,因此要“存储”该值,只需将其传递给该调用。

我为您可以长期使用的浮点值准备了此字段

class DoubleTextDocument extends PlainDocument {
    public void insertString(int offs, String str, AttributeSet a)
            throws BadLocationException {
        if (str == null)
            return;
        String oldString = getText(0, getLength());
        String newString = oldString.substring(0, offs) + str
                + oldString.substring(offs);
        try {
            Float.parseFloat(newString + "0");
            super.insertString(offs, str, a);
        } catch (NumberFormatException e) {
        }
    }
}
在扩展的
JTextField
中,您可以使用

@覆盖

protected Document createDefaultModel() {
    return new DoubleTextDocument();
}
这是一个很好的解决方案

John Zukowski在第542-546页提供了一个很好的示例,展示了一个用于限制整数范围的自定义文档过滤器


提供自定义文档过滤器应该很容易适应在一个注释中指定复制/ PASE中删除不想要的字符的要求。

也考虑,在.

中讨论。使用<代码> JFrastDeTeXField有什么不对吗?我可以这样做,但是它的行为不符合我所希望的。如果焦点丢失,您要么丢失更改并恢复到以前保存的文本(我不想要),要么保留无效文本(我也不想要)。要强制执行此行为,我只需重写它并在不同的事件中编写some代码。
JFormattedTextField
的问题是,您可以输入任何您喜欢的内容。只有在您退出文本字段后,才会进行验证。我在文档实现中遇到的主要问题是它没有按照我希望的方式工作。如果添加了多个字符,但只有少数字符无效,它将吃掉所有字符并恢复到以前的安全值,而不仅仅是清除无效字符。话虽如此,这是我迄今为止想到的第二个最好的选择。我希望有人有一些东西,本质上是一个重构的,更好地考虑了我所拥有的东西。好吧,那么你需要一个场景,在这个场景中,如果发生字母数字文本的复制粘贴,只需要考虑数字部分。对不起,我应该在主要帖子中明确指出这是一个限制。我简要地查看了DocumentFilter,并认为我看到了一些东西,使我认为这是一个交易破坏者。我对它不太熟悉,所以完全可能是我弄错了。我再看一看,谢谢。正如祖考斯基所说:虽然您当然可以创建文档的自定义子类,但更面向对象的方法是创建一个过滤器,因为您不想更改文档;你只是想限制模型的输入。我怀疑我会在这个例子中使用它,但经过一些研究后,我可能会回去创建一些通用的DocumentFilter,并将它们放入一个util包中。我认为这将有一点太多的开销,我要立即使用它们,但它们将是一个很好的长期解决方案。谢谢你的提醒。这和JFormattedTextField有相同的问题,它只在获得/失去焦点时起作用,我需要这个字段进行持续验证。