JFormattedTextFieldMask格式掩码

wen java案例 1

本文目录导读:

JFormattedTextFieldMask格式掩码

  1. 方法一:使用 MaskFormatter(推荐)
  2. 方法二:自定义 DocumentFilter
  3. 常见问题
  4. 完整示例(直接运行)

在 Java Swing 中,JFormattedTextField 本身并没有像第三方控件那样直接提供一个“格式掩码”的字符串属性( 用于电话号码),要实现掩码效果(即限制输入格式并自动填充),通常有两种主要方法:

  1. 使用 MaskFormatter(最常用,推荐)。
  2. 使用自定义的 DocumentFilter(更灵活,但代码量更多)。

以下详细介绍如何使用 MaskFormatter 来实现格式掩码。


使用 MaskFormatter(推荐)

这是实现输入掩码最标准的方式,它允许你定义一个字符串模板,其中特定字符表示允许的输入类型。

常用掩码字符

字符 含义
数字 (0-9)
转义字符(用于将特殊字符视为普通文本)
U 大写字母 (A-Z)
L 小写字母 (a-z)
A 字母或数字
字母 (a-zA-Z)
任意字符
H 十六进制数字 (0-9, a-f, A-F)

代码示例

import javax.swing.*;
import javax.swing.text.MaskFormatter;
import java.text.ParseException;
public class MaskFormatterExample {
    public static void main(String[] args) {
        JFrame frame = new JFrame("MaskFormatter Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(300, 200);
        frame.setLayout(new java.awt.FlowLayout());
        // 1. 创建 MaskFormatter
        MaskFormatter phoneFormatter = null;
        try {
            // 定义掩码模式:固定格式 (123) 456-7890
            phoneFormatter = new MaskFormatter("(###) ###-####");
            phoneFormatter.setPlaceholderCharacter('_'); // 占位符
            phoneFormatter.setAllowsInvalid(false);     // 不允许无效输入
            phoneFormatter.setValidCharacters("0123456789");
        } catch (ParseException e) {
            e.printStackTrace();
        }
        // 2. 创建 JFormattedTextField 并关联 MaskFormatter
        JFormattedTextField phoneField = new JFormattedTextField(phoneFormatter);
        phoneField.setColumns(15);
        phoneField.setValue("1234567890"); // 设置默认值(可选)
        // 示例2:日期掩码 (MM/DD/YYYY)
        MaskFormatter dateFormatter = null;
        try {
            dateFormatter = new MaskFormatter("##/##/####");
            dateFormatter.setPlaceholderCharacter('_');
        } catch (ParseException e) {
            e.printStackTrace();
        }
        JFormattedTextField dateField = new JFormattedTextField(dateFormatter);
        dateField.setColumns(10);
        // 示例3:邮编掩码
        MaskFormatter zipFormatter = null;
        try {
            zipFormatter = new MaskFormatter("#####-####");
            zipFormatter.setPlaceholderCharacter('_');
        } catch (ParseException e) {
            e.printStackTrace();
        }
        JFormattedTextField zipField = new JFormattedTextField(zipFormatter);
        zipField.setColumns(10);
        // 添加到窗口
        frame.add(new JLabel("Phone:"));
        frame.add(phoneField);
        frame.add(new JLabel("Date:"));
        frame.add(dateField);
        frame.add(new JLabel("ZIP:"));
        frame.add(zipField);
        frame.setVisible(true);
    }
}

关键方法

  • setPlaceholderCharacter(char):设置未输入位置的占位符(如 、` `)。
  • setAllowsInvalid(boolean)
    • true:允许输入不符合掩码的字符(直到提交时才验证)。
    • false:即时阻止无效输入(推荐用于掩码)。
  • setValidCharacters(String):限制允许的输入字符集(例如只允许数字)。
  • setPlaceholder(String):设置初始占位文本。

自定义 DocumentFilter

MaskFormatter 无法满足复杂需求(例如需要根据输入动态改变掩码,或更复杂的验证逻辑),可以实现自定义 DocumentFilter

简单示例:只允许数字,并自动添加连字符

import javax.swing.*;
import javax.swing.text.*;
public class CustomMaskFilterExample {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Custom DocumentFilter");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(300, 200);
        frame.setLayout(new java.awt.FlowLayout());
        JFormattedTextField textField = new JFormattedTextField();
        textField.setColumns(15);
        textField.setDocument(new PlainDocument() {
            @Override
            public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
                // 1. 只允许数字
                if (str == null || !str.matches("\\d+")) {
                    // 可以选择忽略,或者提示错误
                    // super.insertString(offs, str, a); // 这样会允许字符
                    return; // 拒绝非数字字符
                }
                // 2. 获取当前文本
                String currentText = getText(0, getLength());
                // 3. 构建新文本
                String newText = new StringBuilder(currentText)
                        .insert(offs, str)
                        .toString();
                // 4. 清理非数字
                newText = newText.replaceAll("[^0-9]", "");
                // 5. 限制长度(10 位)
                if (newText.length() > 10) {
                    newText = newText.substring(0, 10);
                }
                // 6. 套用格式(123-456-7890)
                StringBuilder formatted = new StringBuilder();
                for (int i = 0; i < newText.length(); i++) {
                    if (i == 3 || i == 6) {
                        formatted.append("-");
                    }
                    formatted.append(newText.charAt(i));
                }
                // 7. 直接替换整个文本(避免多次触发)
                // 使用 SwingUtilities.invokeLater 避免递归
                SwingUtilities.invokeLater(() -> {
                    try {
                        remove(0, getLength());
                        super.insertString(0, formatted.toString(), a);
                    } catch (BadLocationException e) {
                        e.printStackTrace();
                    }
                });
            }
        });
        frame.add(new JLabel("Phone (###-###-####):"));
        frame.add(textField);
        frame.setVisible(true);
    }
}

特点 MaskFormatter 自定义 DocumentFilter
易用性 非常简单,几行代码即可 需要编写较多代码
功能 基础掩码、字符验证、占位符 完全可控,可实现复杂逻辑
灵活性 较低,格式固定 极高,可以动态变化
推荐场景 常见格式(电话、日期、SSN) 复杂或动态掩码需求

常见问题

  1. MaskFormatter 无法输入?
    • 检查 setAllowsInvalid(false) 是否阻止了正常输入。
    • 确保使用的掩码字符正确( 只允许数字,L 只允许字母)。
  2. 如何获取 MaskFormatter 的最终值?
    • 使用 textField.getText() 获取当前显示的文本(包含占位符)。
    • 使用 textField.getValue() 获取经过格式化的对象(通常是 String),但不包含占位符。
  3. 如何清空 MaskFormatter 的输入?
    • 直接 textField.setValue(null) 会使其显示占位符,但可能不美观。
    • 推荐:textField.setText("")textField.setValue("")

完整示例(直接运行)

将上面的第一个例子编译运行,你将看到三个带有占位符 的格式化文本框,并且只能输入数字和特定格式。

抱歉,评论功能暂时关闭!