JTextField显示和实际文本 - 波斯语/阿拉伯数字

问题描述 投票:0回答:1

我们正在寻找一种方法来为JTextField保留两种类型的文本

  1. 实际值是用户使用键盘输入的值
  2. 转换后的值是用户在该文本字段中看到的值(这样做的原因是我们希望在他/她键入时向我们的用户显示波斯数字 - 仅显示)

最后,实际文本将保存在我们的数据库中而不是显示文本

我们已经为Display显示了文本转换器,但我们不知道如何将此场景应用于JTextField

java swing jtextfield
1个回答
0
投票

我经历了这个,我想出了这个解决方案。

首先,当他们在操作系统中选择波斯语/阿拉伯语键盘并且他们在JTextField中键入数字时,我们需要显示用户波斯语/阿拉伯语数字。为此,我编写了这个自定义DocumentFilter:

public class PersianNumberDocumentFilter extends DocumentFilter {
    private static final String REPLACE_CHARS = "0123456789.";

    @Override
    public void insertString(FilterBypass fb, int offset, String text,
                             AttributeSet attr) throws BadLocationException {
        if (text != null && !text.isEmpty() && REPLACE_CHARS.contains(text)) {
            text = doSwap(text);
        }
        super.insertString(fb, offset, text, attr);
    }

    @Override
    public void replace(FilterBypass fb, int offset, int length, String text,
                        AttributeSet attrs) throws BadLocationException {
        if (text != null && !text.isEmpty() && REPLACE_CHARS.contains(text)) {
            text = doSwap(text);
        }
        super.replace(fb, offset, length, text, attrs);
    }

    @Override
    public void remove(FilterBypass fb, int offset, int length)
            throws BadLocationException {
        super.remove(fb, offset, length);
    }

    public String doSwap(String text) {
        InputContext context = InputContext.getInstance();
        String windowsKeyboardSelected = context.getLocale().toString();
        if (!windowsKeyboardSelected.contains("fa") && !windowsKeyboardSelected.contains("ar")) {
            return text;
        }

        StringBuilder sb = new StringBuilder();
        for (char c : text.toCharArray()) {
            if (REPLACE_CHARS.contains(String.valueOf(c))) {
                if (c == '.') {
                    c = ',';
                } else {
                    c = (char) ('\u06F0' - '0' + c);
                    //c = (char) ('\u0660' - '0' + c); Arabic Number Digits
                }
            }
            sb.append(c);
        }

        return sb.toString();
    }
}

接下来,我们需要一个实用程序类,用于从波斯语/阿拉伯语进行数字和文本转换。我为这件事写了这个实用程序类:

public class PersianNumber {
    private static HashMap<Character, String> unicodeMap = new HashMap<>();
    private static HashMap<Character, String> unicodeMapArabic = new HashMap<>();
    private static HashMap<Character, String> unicodeMapViceVera = new HashMap<>();

    static {
        //English/Persian Numbers Map
        unicodeMap.put('0', "\u06F0");
        unicodeMap.put('1', "\u06F1");
        unicodeMap.put('2', "\u06F2");
        unicodeMap.put('3', "\u06F3");
        unicodeMap.put('4', "\u06F4");
        unicodeMap.put('5', "\u06F5");
        unicodeMap.put('6', "\u06F6");
        unicodeMap.put('7', "\u06F7");
        unicodeMap.put('8', "\u06F8");
        unicodeMap.put('9', "\u06F9");

        //English/Arabic Numbers Map
        unicodeMapArabic.put('0',"\u0660");
        unicodeMapArabic.put('1',"\u0661");
        unicodeMapArabic.put('2',"\u0662");
        unicodeMapArabic.put('3',"\u0663");
        unicodeMapArabic.put('4',"\u0664");
        unicodeMapArabic.put('5',"\u0665");
        unicodeMapArabic.put('6',"\u0666");
        unicodeMapArabic.put('7',"\u0667");
        unicodeMapArabic.put('8',"\u0668");
        unicodeMapArabic.put('9',"\u0669");

        //Persian English Numbers Map
        unicodeMapViceVera.put('\u06F0', "0");
        unicodeMapViceVera.put('\u06F1', "1");
        unicodeMapViceVera.put('\u06F2', "2");
        unicodeMapViceVera.put('\u06F3', "3");
        unicodeMapViceVera.put('\u06F4', "4");
        unicodeMapViceVera.put('\u06F5', "5");
        unicodeMapViceVera.put('\u06F6', "6");
        unicodeMapViceVera.put('\u06F7', "7");
        unicodeMapViceVera.put('\u06F8', "8");
        unicodeMapViceVera.put('\u06F9', "9");
        //Arabic English Numbers Map
        unicodeMapViceVera.put('\u0660', "0");
        unicodeMapViceVera.put('\u0661', "1");
        unicodeMapViceVera.put('\u0662', "2");
        unicodeMapViceVera.put('\u0663', "3");
        unicodeMapViceVera.put('\u0664', "4");
        unicodeMapViceVera.put('\u0665', "5");
        unicodeMapViceVera.put('\u0666', "6");
        unicodeMapViceVera.put('\u0667', "7");
        unicodeMapViceVera.put('\u0668', "8");
        unicodeMapViceVera.put('\u0669', "9");
    }

    public static String getPersianNumber(String englishNumber) {
        if (!englishNumber.matches("-?\\d+(\\.\\d+)?")) {
            throw new NumberFormatException("the input [" + englishNumber + "] is not a number!");
        }

        char[] numChars = englishNumber.toCharArray();
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < numChars.length; i++) {
            builder.append(unicodeMap.get(numChars[i]));
        }
        return builder.toString();
    }

    public static String getEnglishNumber(String persianNumber) {
        char[] numChars = persianNumber.toCharArray();
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < numChars.length; i++) {
            String value = unicodeMapViceVera.get(numChars[i]);
            if(value == null){
                builder.setLength(0);
                builder.append(persianNumber);
                break;
            }
            builder.append(unicodeMapViceVera.get(numChars[i]));
        }
        return builder.toString();
    }

    public static boolean isAPersianNumber(String persianNumber){
        char[] numChars = persianNumber.toCharArray();
        for (int i = 0; i < numChars.length; i++) {
            String value = unicodeMapViceVera.get(numChars[i]);
            if(value == null){
                return false;
            }
        }
        return true;
    }

    public static String convertToStringWithPersianNumber(String input){
        StringBuilder sb = new StringBuilder();

        for(char c : input.toCharArray()){
            String ch = unicodeMap.get(c);
            if(ch != null){
                sb.append(ch);
                continue;
            }
            sb.append(c);
        }

        return sb.toString();
    }

    public static String convertToStringWithEnglishNumber(String input){
        StringBuilder sb = new StringBuilder();

        for(char c : input.toCharArray()){
            String ch = unicodeMapViceVera.get(c);
            if(ch != null){
                sb.append(ch);
                continue;
            }
            sb.append(c);
        }

        return sb.toString();
    }

    public static void main(String[] args) {
        System.out.println(getEnglishNumber("۹۶۵۹۴۵۴"));
        System.out.println(getPersianNumber("9999999999999651221"));
        System.out.println(getPersianNumber(59683399623213L + ""));
    }
}

最后,我们需要一个自定义JTextField,因为我们希望控制输入和输出并相应地将它们转换为我们的需求:

public class JPersianTextField2 extends JTextField {


    public JPersianTextField2() {
//        Hopefully someday (Oracle Love Iranians) and create This Locale for us
        Locale locale = new Locale("fa", "IR");
//        Locale locale = new Locale("ar", "KW");
        ComponentOrientation farsiOrientation = ComponentOrientation.getOrientation(locale);
        super.applyComponentOrientation(farsiOrientation);
        PlainDocument doc = (PlainDocument) super.getDocument();
        doc.setDocumentFilter(new PersianNumberDocumentFilter());
        super.setColumns(25);
    }

    @Override
    public String getText() {
        String tmp = super.getText();
        if (tmp != null && !tmp.isEmpty())
            return PersianNumber2.convertToStringWithEnglishNumber(tmp);
        else
            return super.getText();
    }

    @Override
    public void setText(String t) {
        if (t != null && !t.isEmpty())
            super.setText(PersianNumber2.convertToStringWithPersianNumber(t));
    }

}

使用此自定义JTextField,当您想要获取JTextField的结果并在您想要设置具有英文数字的String时转换为波斯数字,您可以转换为英文数字。

最后,这是组件的测试:

public class MyFormatterTest extends JFrame {

    public MyFormatterTest() {

        setTitle("Example");
        JPanel panel = new JPanel();
        JLabel label = new JLabel("text :");
        JPersianTextField2 tf = new JPersianTextField2();
        tf.setText("سلام من مهدی هستم برنامه نویس ارشد 31 ساله"); //Hi This is mehdi, 31 years old Sr. software developer
        panel.add(label);
        panel.add(tf);

        JButton button2 = new JButton();
        button2.setText("getText");
        button2.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println(tf.getText());
            }
        });

        panel.add(button2);


        getContentPane().add(panel, BorderLayout.SOUTH);
        pack();

    }

    public static void main(String[] args) {

        //Available Locales inside Your JVM
        for (Locale l : Locale.getAvailableLocales()) {
            System.out.println(l.getCountry() + ":" + l.getLanguage());
        }

        MyFormatterTest mfe = new MyFormatterTest();
        mfe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mfe.setVisible(true);
    }
}

希望这对你有用......

© www.soinside.com 2019 - 2024. All rights reserved.