`
沐疯-
  • 浏览: 12826 次
  • 性别: Icon_minigender_1
  • 来自: 山东
社区版块
存档分类
最新评论

JFormattedTextField使用心得

阅读更多

文本框是使用率非常高的一个控件, 用于接收用户的输入信息。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的各种功能都讲解完了。最后在强调一下该控件的一个容易让人犯错误的地方:以上各种机制有效的前提是,对话框没有被关闭!!!换句话说,如果是一个登陆框,用户输入完信息后点“确定”,然后登陆框被关闭,那么上述各种机制均无效。你不要天真的以为用户输入错误焦点就不会离开,对话框都关闭了,何谈焦点?因此,如果你的对话框有一个“确定”按钮能关闭对话框,那么你最好在按钮的点击事件中检测一下各个文本框的格式是否真的正确再关闭,否则后果很严重地~

分享到:
评论

相关推荐

    java swing-JFormattedTextField的使用

    JFormattedTextField是Swing库提供的一个带有格式的文本输入框组件。它允许用户输入特定格式的数据,例如日期、时间、货币等,并在用户输入时进行格式验证。

    如何使用掩码格式化文本框

    3. **Java**:在Java Swing中,我们可以使用`JFormattedTextField`与`MaskFormatter`结合来实现掩码。以下是一个例子: ```java MaskFormatter formatter = new MaskFormatter("(999) 999-9999"); ...

    AutoText:Java Swing 库,允许将自动完成的可能性添加到文本组件(JTextComponent - JTextField - JFormattedTextField 等)

    5. **配置和使用**: 配置AutoText可能涉及设置自动完成的数据源、触发自动完成的条件(如用户输入达到一定字符数)、显示建议的方式(如弹出窗口或下拉列表)等。开发者需要按照库提供的API进行集成和定制。 6. **...

    仿Windows的IP和MAC输入框

    要创建仿Windows的IP输入框,我们可以使用`JFormattedTextField`,它允许我们限制用户输入的格式。对于IP地址,我们需要四个0-255之间的数字,每个数字之间用点分隔。首先,定义一个自定义的格式器,如`...

    Java设计类似微软IP地址输入框

    在Java中,我们可以使用JTextField或JFormattedTextField来创建这个输入框。JFormattedTextField允许我们设置输入格式,从而确保用户输入的数据符合特定的模式。对于IP地址,我们可以创建一个自定义的格式模型,例如...

    疯狂JAVA讲义

    学生提问:当我们使用编译C程序时,不仅需要指定存放目标文件的位置,也需要指定目标文件的文件名,这里使用javac编译Java程序时怎么不需要指定目标文件的文件名呢? 13 1.5.3 运行Java程序 14 1.5.4 根据...

    java swing 日期datepicker组件使用

    JDatePicker通常包括一个组合的JFormattedTextField,展示所选日期,并且附带一个弹出的日历视图供用户选择日期。在项目中,你可能会看到如何创建、配置JDatePicker,设置其日期格式,以及如何监听日期改变事件。 2...

    日期选择框架包 Jdatepicker-1.3.4jar

    这个框架的核心是一个轻量级的JPanel,内含一个JFormattedTextField和一个可配置的日历小部件,使得用户能够直观地选择日期。 首先,JDatePicker的API设计简洁,易于集成到现有的Swing应用中。开发者可以通过简单的...

    全部代码

    - 对于需要格式化输入的情况,如日期、电话号码等,可以使用`JFormattedTextField`,它继承自`JTextField`,提供了一种控制用户输入格式的方法。 6. **布局管理**: - 在Swing中,`JTextField`通常与其他组件一起...

    javaSE代码实例

    1.3 学会使用API 7 1.4 第一个Java程序 8 1.4.1 开发源代码 8 1.4.2 编译运行 9 1.5 小结 11 第2章 基本数据类型——构建Java 大厦的基础 12 2.1 源代码注释 12 2.1.1 单行注释 12 2.1.2 区域...

    Java 编写 闹钟程序 使用路径绘制指针 可选择闹铃音乐

    这需要添加额外的输入字段,如JSpinner或JFormattedTextField,以及相应的事件处理代码。 10. **线程管理**:考虑到时钟的实时性和用户交互的响应性,可能需要在后台线程中执行定时任务,以免阻塞主线程。Java的...

    如果右键单机文本域会弹出美观的日历控件

    它们都使用了 `SpinnerNumberModel`,这是一个预定义的模型,允许用户在指定范围内进行数值选择。 2. **JFormattedTextField**: - `JFormattedTextField` 是Swing中的另一个重要组件,它可以显示和编辑格式化的...

    计算机简单功能Java实现的

    对于数字输入,开发者可能使用了JTextField或者JFormattedTextField来显示当前的计算表达式。JTextField是最基本的文本输入组件,而JFormattedTextField则允许对输入的格式进行限制,比如只接受数字,这对于计算器来...

    javaSwing日期的控件

    JFormattedTextField约会字段 = new JFormattedTextField(date,(formatterFactory)); JDatePicker datePicker = new JDatePicker(date约会字段, new DefaultDatePickerModel()); frame.add(datePicker); frame...

    用javaGUI做的阳光酒店管理系统

    4. **账单计算**:根据客户入住的天数、房型等计算费用,使用JSpinner或JFormattedTextField来输入和显示数值。 5. **员工管理**:记录员工信息,分配权限,监控工作进度,可能有自定义的JPanel来实现特定功能。 6...

    java时间控件

    JDatePicker可以附加到JFormattedTextField,使得用户输入的日期能自动格式化,并且可以通过设置日期模型来限制可选日期范围。 3. **JavaFX DatePicker**: 如果你使用JavaFX作为UI框架,DatePicker是内置的时间控件...

    java的swing实现计时与倒计时

    在处理时间输入时,我们可以使用JFormattedTextField或JSpinner,它们允许用户以预定义的格式输入数据。我们可以设定格式为24小时制的HH:mm:ss,以确保用户输入的时间有效。 接着,我们使用多线程来实现计时和倒...

    北航版Java基础与实例精解9-17章源码

    9. **例12.32 格式文本框**:可能涉及到JFormattedTextField的使用,该组件允许用户输入符合特定格式的数据,如日期、数字等。 10. **例16.15 使用GeneralPath类绘制任意图形**:GeneralPath是一个用于构建几何路径...

    java模拟时钟(新)

    - 创建一个时间设置对话框,可以包含三个`JSpinner`或`JFormattedTextField`,分别对应小时、分钟和秒。 - 用户调整时间后,更新内部的时间存储并同步到模拟时钟和数字时钟的显示。 6. **事件处理**: - `...

    edu.ood.sharanya.project1.DateDiff_Swing.zip_The Swing

    对于这个“DateDiff_Swing”项目,开发者可能首先创建了一个Swing GUI,包含输入字段让用户输入两个日期,比如可能有两个`JTextField`或`JFormattedTextField`,分别表示起始日期和结束日期。用户提交后,程序会使用...

Global site tag (gtag.js) - Google Analytics