https://lanlan2017.github.io/JavaReadingNotes/93fa3225/

https://blog.csdn.net/yellow216000/article/details/84743258

 https://lanlan2017.github.io/JavaReadingNotes/93fa3225/

 

12.12.3 使用JFormattedTextField

合理输入问题

在有些情况下,程序不希望用户在输入框内随意地输入,例如,程序需要用户输入一个有效的时间,或者需要用户输入一个有效的物品价格,如果用户输入不合理,程序应该阻止用户输入。

使用事件监听实现

对于这种需求,通常的做法是为该文本框添加失去焦点的监听器,再添加回车按键的监听器,当该文本框失去焦点时,或者该用户在该文本框内按回车键时,就检测用户输入是否合法。这种做法基本可以解决该问题,但编程比较烦琐!

使用JFormattedTextField

Swing提供的JFormattedTextField可以更优雅地解决该问题。

JFormattedTextField和普通文本行的区别

使用JFormattedTextField与使用普通文本行有一个区别:

  • 它需要指定一个文本格式,只有当用户的输入满足该格式时,JFormattedTextField才会接收用户输入。

JFormattedTextField格式分类

JFormattedTextField可以使用如下两种类型的格式。

  • JFormattedTextField.AbstractFormatter:该内部类有一个子类DefaultFormatter,而DefaultFormatter又有一个非常实用的MaskFormatter子类,允许程序以掩码的形式指定文本格式
  • Format:主要由DateFormatNumberFormat两个格式器组成,这两个格式器可以指定JFormattedTextField所能接收的格式字符串。

JFormattedTextField方法

创建JFormattedTextField对象时可以传入上面任意一个格式器:

构造器描述
JFormattedTextField(Format format) Creates a JFormattedTextField.

成功地创建了JFormattedTextField对象之后,JFormattedTextField对象的用法和普通TextField的用法基本相似,一样可以调用setColumns()来设置该文本框的宽度,调用setFont()来设置该文本框内的字体等。
除此之外,JFormattedTextField还包含如下三个特殊方法

JFormattedTextField类的方法描述
Object getValue() 获取该格式化文本框里的值
void setValue(Object value) 设置该格式化文本框的初始值
void setFocusLostBehavior(int behavior) 设置该格式化文本框失去焦点时的行为。

getValue方法

上面三个方法中获取格式化文本框内容的getValue方法返回Object类型,而不是返回String类型;

setValue方法

与之对应的是,设置格式化文本框初始值的setValue方法需要传入Object类型参数,而不是String类型参数。
这都是因为格式化文本框会将文本框内容转换成指定格式对应的对象,而不再是普通字符串。

setFocusLostBehavior方法

setFocusLostBehavior方法可以接收如下4个值:

setFocusLostBehavior方法参数值描述
JFormattedTextField.COMMIT 如果用户输入的内容满足格式器的要求,则该格式化文本框显示的文本变成用户输入的内容,调用getValue()方法返回的是该文本框内显示的内容;如果用户输入的内容不满足格式器的要求,则该格式化文本框显示的依然是用户输入的内容,但调用getValue()方法返回的不是该文本框内显示的内容,而是上一个满足要求的值
JFormattedTextField.COMMIT_OR_REVERT 这是默认值。如果用户输入的内容满足格式器的要求,则该格式化文本框显示的文本、getValue()方法返回的都是用户输入的内容;如果用户输入的内容不满足格式器的要求,则该格式化文本框显示的文本、getValue()方法返回的都是上一个满足要求的值。
JFormattedTextField.REVERT 不管用户输入的内容是否满足格式器的要求,该格式化文本框都显示用户输入的内容,getValue()方法返回的都是上一个满足要求的值。
JFormattedTextField.PERSIST 不管用户输入的内容是否满足格式器的要求,该格式化文本框显示的内容、getValue()方法返回的都是上一个满足要求的值。在这种情况下,不管用户输入什么内容对该文本框都没有任何影响。

DefaultFormatter

DefaultFormatter是一个功能非常强大的格式器,它可以格式化任何类的实例,只要该类包含带一个字符串参数的构造器,并提供对应的toString()方法(该方法的返回值就是传入给构造器字符串参数的值)即可
例如,URL类包含一个URL(String spec)构造器,且URL对象的toString()方法恰好返回刚刚传入的spec参数,因此可以使用DefaultFormatter来格式化URL对象。当格式化文本框失去焦点时,该格式器就会调用带一个字符串参数的构造器来创建新的对象,如果构造器抛出了异常,即表明用户输入无效。
DefaultFormatter格式器默认采用改写方式来处理用户输入,即当用户在格式化文本框内输入时,每输入一个字符就会替换文本框内原来的一个字符。如釆想关闭这种改写方式,采用插入方式,则可通过调用它的setOverwriteMode(false)方法来实现。

MaskFormatter

MaskFormatter格式器的功能有点类似于正则表达式,它要求用户在格式化文本框内输入的内容必须匹配一定的掩码格式。例如,若要匹配广州地区的电话号码,则可采用020-########的格式,这个掩码字符串和正则表达式有一定的区别,因为该掩码字符串只支持如下通配符。

  • #:代表任何有效数字
  • ‘:转义字符,用于转义具有特殊格式的字符。例如,若想匹配#,则应该写成’#
  • U:任何字符,将所有小写字母映射为大写。
  • L:任何字符,将所有大写字母映射为小写。
  • A:任何字符或数字。
  • ?:任何字符。
  • *:可以匹配任何内容。
  • H:任何十六进制字符(0~9a~fA~F)。

值得指出的是,格式化文本框内的字符串总是和掩码具有相同的格式,连长度也完全相同。如果用户删除了格式化文本框内的字符,这些被删除的字符将由占位符替代。默认使用空格作为占位符,当然也可以调用MaskFormattersetPlaceholderCharacter()方法来设置该格式器的占位符。例如如下代码:

1
formatter.setPlaceholdercharacter(' ');
复制

程序

下面程序示范了关于JFormattedTextField的简单用法。

上面程序添加了6个格式化文本框,其中两个是基于NumberFormat生成的整数格式器、货币格式器,两个是基于DateFormat生成的日期格式器,一个是使用DefaultFormatter创建的URL格式器,最后一个是使用MaskFormatter创建的掩码格式器,程序中的粗体字代码是创建这些格式器的关键代码。
除此之外,程序还添加了4个单选按钮,用于控制这些格式化文本框失去焦点后的行为。运行上面程序,并选中“COMMIT”行为,将看到如图12.59所示的界面
从图12.59中可以看出,虽然用户向格式化文本框内输入的内容与该文本框所要求的格式不符,但该文本框依然显示了用户输入的内容,只是后面显示该文本框的getValue()方法返回值时看到的依然是100,即上一个符合格式的值。
大部分时候,使用基于Format的格式器,DefaultFormatterMaskFormatter已经能满足绝大部分要求;但对于一些特殊的要求,则可以采用扩展DefaultFormatter的方式来定义自己的格式器。定义自己的格式器通常需要重写DefaultFormatter的如下两个方法

方法描述
Object stringToValue(String string) 根据格式化文本框内的字符串来创建符合指定格式的对象。
String valueToString(Object value) 将符合格式的对象转换成文本框中显示的字符串

例如,若需要创建一个只能接收IP地址的格式化文本框,则可以创建一个自定义的格式化文本框,因为IP地址是由4个0~255之间的整数表示的,所以程序采用长度为4的byte数组来保存IP地址,程序可以采用如下方法将用户输入的字符串转换成byte数组。

如何保证用户输入的有效性

除此之外,Swing还提供了如下两种机制来保证用户输入的有效性

  • 输入过滤:输入过滤机制允许程序拦截用户的插入、替换、删除等操作,并改变用户所做的修改。
  • 输入校验:输入验证机制允许用户离开输入组件时,验证机制自动触发——如果用户输入不符合要求,校验器强制用户重新输入。

输入过滤器

输入过滤器需要继承DocumentFilter类,程序可以重写该类的如下三个方法来拦截用户的插入、删除和替换等操作。

方法描述
void insertString(DocumentFilter.FilterBypass fb, int offset, String string, AttributeSet attr) 该方法会拦截用户向文档中插入字符串的操作。
void remove(DocumentFilter.FilterBypass fb, int offset, int length) 该方法会拦截用户从文档中删除字符串的操作。
void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attrs) 该方法会拦截用户替换文档中字符串的操作。

输入校验器

为了创建自己的输入校验器,可以通过扩展InputVerifier类来实现。实际上,InputVerifier输入校验器可以绑定到任何输入组件,InputVerifier类里包含了一个verify(JComponent component)方法,当用户在该输入组件内输入完成,且该组件失去焦点时,该方法被调用,如果该方法返回false,即表明用户输入无效,该输入组件将自动得到焦点。也就是说,如果某个输入组件绑定了InputVerifier,则用户必须为该组件输入有效内容,否则用户无法离开该组件。
有一种情况例外,如果输入焦点离开了带InputVerifier输入校验器的组件后,立即单击某个按钮,则该按钮的事件监听器将会在焦点重新回到原组件之前被触发。

程序 为格式化文本框 添加输入过滤器 输入校验器

下面程序示范了如何为格式化文本框添加输入过滤器、输入校验器,程序还自定义了一个IP地址格式器,该IP地址格式器扩展了DefaultFormatter格式器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import java.util.*;
import java.text.*;
import java.net.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.text.*;

public class JFormattedTextFieldTest
{
private JFrame mainWin = new JFrame("测试格式化文本框");
private JButton okButton = new JButton("确定");
// 定义用于添加格式化文本框的容器
private JPanel mainPanel = new JPanel();
JFormattedTextField[] fields = new JFormattedTextField[6];
String[] behaviorLabels = new String[]
{
"COMMIT",
"COMMIT_OR_REVERT",
"PERSIST",
"REVERT"
};
int[] behaviors = new int[]
{
JFormattedTextField.COMMIT,
JFormattedTextField.COMMIT_OR_REVERT,
JFormattedTextField.PERSIST,
JFormattedTextField.REVERT
};
ButtonGroup bg = new ButtonGroup();
public void init()
{
// 添加按钮
JPanel buttonPanel = new JPanel();
buttonPanel.add(okButton);
mainPanel.setLayout(new GridLayout(0, 3));
mainWin.add(mainPanel, BorderLayout.CENTER);
// 使用NumberFormat的integerInstance创建一个JFormattedTextField
fields[0] = new JFormattedTextField(NumberFormat
.getIntegerInstance());
// 设置初始值
fields[0].setValue(100);
addRow("整数格式文本框 :", fields[0]);
// 使用NumberFormat的currencyInstance创建一个JFormattedTextField
fields[1] = new JFormattedTextField(NumberFormat
.getCurrencyInstance());
fields[1].setValue(100.0);
addRow("货币格式文本框:", fields[1]);
// 使用默认的日期格式创建一个JFormattedTextField对象
fields[2] = new JFormattedTextField(DateFormat.getDateInstance());
fields[2].setValue(new Date());
addRow("默认的日期格式器:", fields[2]);
// 使用SHORT类型的日期格式创建一个JFormattedTextField对象,
// 且要求采用严格日期格式
DateFormat format = DateFormat.getDateInstance(DateFormat.SHORT);
// 要求采用严格的日期格式语法
format.setLenient(false);
fields[3] = new JFormattedTextField(format);
fields[3].setValue(new Date());
addRow("SHORT类型的日期格式器(语法严格):", fields[3]);
try
{
// 创建默认的DefaultFormatter对象
DefaultFormatter formatter = new DefaultFormatter();
// 关闭overwrite状态
formatter.setOverwriteMode(false);
fields[4] = new JFormattedTextField(formatter);
// 使用DefaultFormatter来格式化URL
fields[4].setValue(new URL("http://www.crazyit.org"));
addRow("URL:", fields[4]);
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
try
{
MaskFormatter formatter = new MaskFormatter("020-########");
// 设置占位符
formatter.setPlaceholderCharacter('□');
fields[5] = new JFormattedTextField(formatter);
// 设置初始值
fields[5].setValue("020-28309378");
addRow("电话号码:", fields[5]);
}
catch (ParseException ex)
{
ex.printStackTrace();
}

JPanel focusLostPanel = new JPanel();
// 采用循环方式加入失去焦点行为的单选按钮
for (int i = 0; i < behaviorLabels.length ; i++ )
{
final int index = i;
final JRadioButton radio = new JRadioButton(behaviorLabels[i]);
// 默认选中第二个单选按钮
if (i == 1)
{
radio.setSelected(true);
}
focusLostPanel.add(radio);
bg.add(radio);
// 为所有单选按钮添加事件监听器
radio.addActionListener(e -> {
// 如果当前该单选按钮处于选中状态,
if (radio.isSelected())
{
// 设置所有的格式化文本框的失去焦点的行为
for (int j = 0 ; j < fields.length ; j++)
{
fields[j].setFocusLostBehavior(behaviors[index]);
}
}
});
}
focusLostPanel.setBorder(new TitledBorder(new EtchedBorder(),
"请选择焦点失去后的行为"));
JPanel p = new JPanel();
p.setLayout(new BorderLayout());
p.add(focusLostPanel , BorderLayout.NORTH);
p.add(buttonPanel , BorderLayout.SOUTH);

mainWin.add(p , BorderLayout.SOUTH);
mainWin.pack();
mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainWin.setVisible(true);
}
// 定义添加一行格式化文本框的方法
private void addRow(String labelText, final JFormattedTextField field)
{
mainPanel.add(new JLabel(labelText));
mainPanel.add(field);
final JLabel valueLabel = new JLabel();
mainPanel.add(valueLabel);
// 为"确定"按钮添加事件监听器
// 当用户单击“确定”按钮时,文本框后
okButton.addActionListener(event -> {
Object value = field.getValue();
// 输出格式化文本框的值
valueLabel.setText(value.toString());
});
}
public static void main(String[] args)
{
new JFormattedTextFieldTest().init();
}
}
复制

运行上面程序,会看到窗口中出现三个格式化文本框,其中第一个格式化文本框只能输入数字,其他字符无法输入到该文本框内;第二个格式化文本框有输入校验器,只有当用户输入的内容符合该文本框的要求时,用户才可以离开该文本框;第三个格式化文本框的格式器是自定义的格式器,它要求用户输入的内容是一个合法的IP地址。

 

文本框是使用率非常高的一个控件, 用于接收用户的输入信息。java中有一个最基本的文本框JTextField可以实现这一功能。但是绝大多数情况下,我们都需要对用户输入的内容做某些检测,这时候JTextField就不是那么好用了,实现起来就比较麻烦了。于是java又提供了一个复杂的文本框JFormattedTextField来帮助我们实现一些常用的功能,当然,如果你要实现的功能太复杂,还是老老实实的给JTextField增加监听器吧。
         如果你使用的是JTextField,那么不管这个文本框准备接受的是数字,日期,货币还是ip地址,对于你来讲,你只能通过getText方法得到一个字符串,然后自己写代码把这个字符串转化为相应的数据对象。而JFormattedTextField的内在机制可以将字符串自动转化为相应的数据对象,你既可以通过getText得到字符串,也可以通过getValue方法的到转化后的数据对象(该对象是一个Object对象,还需要强制转化一下)。正是因为JFormattedTextField同时提供了外部显示的字符串和实际的数据对象,我们就可以利用他来完成一些常见的功能。下面我们来简单探讨一下JFormattedTextField的常见的使用方式:
         首先,顾名思义,JFormattedTextField最基本的功能是,“检测格式的正确性”。最常见的就是数字和日期的格式问题,这些格式是全世界通用的,而java中也提供了相应的格式类,可以直接使用,我们来看一下代码:

JFormattedTextField intField =  new JFormattedTextField(NumberFormat.getIntegerInstance());
短短的一行代码就能实现如下功能:当该文本框失去焦点时,检测用户的输入是否符合整数的格式。若不符合整数的格式,则有几种方式来提示用户。默认的方式是丢弃用户的输入,文本框内显示的内容恢复到用户输入前的状态。比如文本框内原来是“123”,你输入了个“abc”,因为“abc”不是一个整数,因此当光标离开文本框后,文本框的内容立刻又变回“123”,并且内部的Value对象仍然是整数123。
        我个人认为这种行为不是一个很好的用户体验,用户辛辛苦苦的输入了很长一串内容,如果仅仅是不小心错了一点,你就把所有内容都变没了,不给用户修改的机会,这是不合适的。无论用户输入的是对是错,你只能给出相应的提示,而不能擅自清除用户的输入。幸好java也考虑到了这一点,你在上述代码的后面再加一句:

        intField.setFocusLostBehavior(JFormattedTextField.COMMIT);
这样用户的错误输入就不会丢失了,但也没有任何提示性信息来告知用户输入错误。同时请注意,虽然文本框内会保留“abc”,但是内部的Value对象仍然是整数123!!
         JFormattedTextField提供了另外一种机制来提示用户输入错误,“如果输入的格式错误,则不允许焦点离开文本框”。换句话说,如果你输入的是“abc”,那么你就别想在其他的文本框里输入内容,焦点会一直停留在此文本框内,直到你输入了正确的整数格式。代码如下:

JFormattedTextField intField =  new JFormattedTextField(NumberFormat.getIntegerInstance());
intField.setInputVerifier( new FormattedTextFieldVerifier());

// 定义一个InputVerifier类,把这个类添加到JFormattedTextField中
class FormattedTextFieldVerifier  extends InputVerifier
{
   public boolean verify(JComponent component)
   {
      JFormattedTextField field = (JFormattedTextField) component;
      //若用户的输入符合格式,则返回true,否则返回false
      return field.isEditValid();
   }
}

大家看到了,上述代码不光为JFormattedTextField添加了一个整数格式,还为他添加了一个验证器类。验证器类中有一个verify方法,此方法若返回ture,则焦点可以离开,此方法若返回false,则焦点不能离开。在此方法中,我们调用isEditValid方法来验证格式的正确与否。isEditValid方法是JFormattedTextField提供的,通过此方法可以很方便的验证格式的正确性。
       当然,我们最常见的错误提示方式是:若用户输入错误,在此文本框的后面出现一个鲜红的“×”。很遗憾JFormattedTextField没有提供这种机制,你只能在他后面添加一个JLabel,然后监听JFormattedTextField的失去焦点事件,若不符合格式,您自己在JLabel上打一个“×”。
         JFormattedTextField还提供了另外一个非常有用的机制:“不允许输入非法字符”。这样您的文本框就可以只接收数字而不接收字母,防止用户的误操作。代码如下:

// 用自定义的DocumentFilter替换格式类中默认的DocumentFilter
JFormattedTextField intField3 =  new JFormattedTextField(
         new InternationalFormatter(NumberFormat.getIntegerInstance())  {
            protected DocumentFilter getDocumentFilter() {
                return filter;
            }
            private DocumentFilter filter = new IntFilter();
        });

// 自定义一个DocumentFilter类
class IntFilter  extends DocumentFilter  {
//重载insertString方法
    public void insertString(FilterBypass fb, int offset, String string,
            AttributeSet attr) throws BadLocationException {
        StringBuilder builder = new StringBuilder(string);
        for (int i = builder.length() - 1; i >= 0; i--) {
            int cp = builder.codePointAt(i);
            if (!Character.isDigit(cp) && cp != '-') {
                builder.deleteCharAt(i);
                if (Character.isSupplementaryCodePoint(cp)) {
                    i--;
                    builder.deleteCharAt(i);
                }
            }
        }
        super.insertString(fb, offset, builder.toString(), attr);
    }
//重载replace方法
    public void replace(FilterBypass fb, int offset, int length, String string,
            AttributeSet attr) throws BadLocationException {
        if (string != null) {
            StringBuilder builder = new StringBuilder(string);
            for (int i = builder.length() - 1; i >= 0; i--) {
                int cp = builder.codePointAt(i);
                if (!Character.isDigit(cp) && cp != '-') {
                    builder.deleteCharAt(i);
                    if (Character.isSupplementaryCodePoint(cp)) {
                        i--;
                        builder.deleteCharAt(i);
                    }
                }
            }
            string = builder.toString();
        }
        super.replace(fb, offset, length, string, attr);
    }
}
原理很简单,就是添加一个过滤器。不过要注意,这个过滤器不是直接添加到JFormattedTextField中,而是替换格式类中默认的过滤器。在过滤器中,你要重载2个方法,分别是insertString和replace。在这2个方法中,把你不希望用户输入的字符过滤掉。但是请注意,不要被这2个方法的名字迷惑了,当你将光标定位到文本框中(不选中任何文字),然后敲击一下键盘,系统会调用哪个方法?是insertString吗?不是,是replace!!!目前为止我还不知道insertString方法会在什么时候被调用,至少在我的程序中,它从来没有被调用过。但是SUN的专家告诉我们“您一定要将insertString这个方法重载,它将在某些时候被调用”。听专家的话一定没错,反正我每次都将他重载了。
         让我们再来看看JFormattedTextField另外一个很有用的机制,“输入固定长度的字符串”。当你的文本框准备接收一个身份证号,手机号码,邮政编码等信息的时候,由于这些信息都是固定长度,并且只有一部分字符是合法字符(0~9),如果我们能做这些限制的话,将大大减少用户出错的可能。你可以为JFormattedTextField添加一个“掩码格式”来实现这一功能。注意,“掩码格式”和前面说的“数值格式”是并列关系,也就是说你只能二取其一,而不能同时享受这两种格式的好处。下面我们来看看代码:

    MaskFormatter formatter =  new MaskFormatter("###########");
    formatter.setPlaceholderCharacter('0');
    JFormattedTextField ssnField =  new JFormattedTextField(formatter);
上述代码就能限制输入一个长度为11位的数字,也就是手机号。
         如果我们要输入的内容格式比较特殊呢,JAVA没有提供现成的格式类,我们该怎么办?比如一个IP地址?比如一个URL网址?JFormattedTextField允许你通过两种方式来实现“自定义特殊格式”。第一种方法,自定义一个格式类,继承DefaultFormatter类,重载valueToString和stringToValue方法(会抛出一个ParseException异常),实现IP地址格式的代码如下:

class IPAddressFormatter  extends DefaultFormatter  {
    public String valueToString(Object value) throws ParseException {
        if (!(value instanceof byte[]))
            throw new ParseException("Not a byte[]", 0);
        byte[] a = (byte[]) value;
        if (a.length != 4)
            throw new ParseException("Length != 4", 0);
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < 4; i++) {
            int b = a[i];
            if (b < 0)
                b += 256;
            builder.append(String.valueOf(b));
            if (i < 3)
                builder.append('.');
        }
        return builder.toString();
    }

    public Object stringToValue(String text) throws ParseException {
        StringTokenizer tokenizer = new StringTokenizer(text, ".");
        byte[] a = new byte[4];
        for (int i = 0; i < 4; i++) {
            int b = 0;
            if (!tokenizer.hasMoreTokens())
                throw new ParseException("Too few bytes", 0);
            try {
                b = Integer.parseInt(tokenizer.nextToken());
            } catch (NumberFormatException e) {
                throw new ParseException("Not an integer", 0);
            }
            if (b < 0 || b >= 256)
                throw new ParseException("Byte out of range", 0);
            a[i] = (byte) b;
        }
        if (tokenizer.hasMoreTokens())
            throw new ParseException("Too many bytes", 0);
        return a;
    }
}
第二种实现方法是直接使用DefaultFormatter,然后调用JFormattedTextField的setValue方法,传递给他的参数必须是一个符合要求的类:该类拥有一个“以一个字符串为参数的构造函数”(会抛出异常,相当于上面的stringToValue方法),还有一个toString方法(也会抛出异常,相当于上面的valueToString方法)。比如一个URL网址,JAVA就有相应的类,我们可以直接使用,代码如下:

    DefaultFormatter formatter =  new DefaultFormatter();
    formatter.setOverwriteMode( false);
    JFormattedTextField urlField =  new JFormattedTextField(formatter);
    urlField.setFocusLostBehavior(JFormattedTextField.COMMIT);
    urlField.setValue( new URL("http://java.sun.com"));
只要用户的输入不符合网址的格式,都可以利用前面讲过的各种机制来提示用户。
         至此,JFormattedTextField的各种功能都讲解完了。最后在强调一下该控件的一个容易让人犯错误的地方:以上各种机制有效的前提是,对话框没有被关闭!!!换句话说,如果是一个登陆框,用户输入完信息后点“确定”,然后登陆框被关闭,那么上述各种机制均无效。你不要天真的以为用户输入错误焦点就不会离开,对话框都关闭了,何谈焦点?因此,如果你的对话框有一个“确定”按钮能关闭对话框,那么你最好在按钮的点击事件中检测一下各个文本框的格式是否真的正确再关闭,否则后果很严重地~

 

 

 

posted on 2021-06-30 10:03  yuluoxingkong  阅读(558)  评论(0编辑  收藏  举报