Java 通往'的更清洁的道路;消毒';JTextField输入?
因此,我正在为一个JTextField编写TextValueChanged处理程序,该处理程序的输入耗时很长。它只需要允许用户键入介于0和Long.MAX之间的有效值。如果用户键入无效字符,则应将其删除,以便JTextField中的值始终为有效长字符 我当前的代码看起来像这样,但看起来很难看。在没有外部lib(包括apachecommons)的情况下,有没有更干净/更简单的方法来实现这一点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
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有相同的问题,它只在获得/失去焦点时起作用,我需要这个字段进行持续验证。