0

我正在开发一个使用 JTextField 让用户输入电话号码的 Swing 应用程序。为安全起见,在用户键入电话号码时,中间的四位数字需要显示为通配符。同时,当电话号码来自数据库时,此 JTextField 还将中间的四位数字显示为通配符。

如何自定义 JTextField?非常感谢任何帮助。

4

1 回答 1

3

使用DocumentFilter.

请参阅此示例,只需new PhoneNumberFilter(6,10,'*')根据您的确切需求进行更改。

FI南非有10位数的电话号码,前3位是拨号代码,其余的是唯一号码。

因此,如果想用 *** 掩盖最后 4 位数字,并且整个电话号码是 10 位数字,我会new PhoneNumberFilter(6,10,'*')标记最后 4 位(10-6=4)。

在此处输入图像描述

import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.DocumentFilter.FilterBypass;

public class Test {

    public Test() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

                //create instance of our custom DocumentFiler class
                PhoneNumberFilter phoneNumberFilter = new PhoneNumberFilter(6, 10, '*');


                JTextField jtf = new JTextField(10);
                //add filter to JTextField
                ((AbstractDocument) jtf.getDocument()).setDocumentFilter(phoneNumberFilter);
                frame.add(jtf);

                frame.pack();
                frame.setVisible(true);

                //jtf.setText("0119887654");
            }
        });
    }

    public static void main(String[] args) {
        new Test();
    }
}

class PhoneNumberFilter extends DocumentFilter {

    private int textLength = 0;//keeps track of length of text within the field (used to check if we should start applying the mask)
    private int numberMaskStartIndex;
    private int numberMaskEndIndex;
    private String mask;//what the characters in the specified ranges positions will be replaced with

    public PhoneNumberFilter(int start, int end, char mask) {
        numberMaskStartIndex = start;
        numberMaskEndIndex = end - 1;
        this.mask = String.valueOf(mask);
    }

    @Override
    public void replace(FilterBypass fb, int i, int i1, String string, AttributeSet as) throws BadLocationException {
        if (string.length() > 1) {
            for (int n = string.length() - 1; n >= 0; n--) {//an inserted string may be more than a single character i.e copy and pasting a number
                char c = string.charAt(n);//get a single character of the string
                if (n >= numberMaskStartIndex && n <= numberMaskEndIndex) {//check if its between the range which we should mask
                    super.replace(fb, i, i1, mask, as);
                } else {
                    super.replace(fb, i, i1, String.valueOf(c), as);
                }
                textLength++;
            }
        } else if (textLength >= numberMaskStartIndex && textLength <= numberMaskEndIndex) {//only a singe character was inserted and its between the range which we should mask
            super.replace(fb, i, i1, mask, as);
            textLength++;
        } else {
            super.replace(fb, i, i1, string, as);
            textLength++;
        }
    }

    @Override
    public void remove(FilterBypass fb, int i, int i1) throws BadLocationException {
        super.remove(fb, i, i1);
        if (i == 0 && i1 == textLength) {//if the text removed is the entire textfield i.e CTRL+A or Mouse dragged and DEL than we reset our counter which keeps track of the number of characters in the textfield
            textLength = 0;
        } else {//only a single character was deleted
            textLength--;
        }
    }

    @Override
    public void insertString(FilterBypass fb, int i, String string, AttributeSet as) throws BadLocationException {
        super.insertString(fb, i, string, as);
    }
}

我没有添加限制用户输入的功能,因此可以输入任何内容,以上更多是为了显示所需的逻辑:

为安全起见,在用户键入电话号码时,中间的四位数字需要显示为通配符。同时,当电话号码来自数据库时,此 JTextField 还将中间的四位数字显示为通配符

您可能仍然会问,从数据库中获取它是否有效,是的,因为 DocumentFilter 也适用于setText(..);

于 2013-06-30T10:01:22.183 回答