当前位置: 首页 > 知识库问答 >
问题:

如何在文本字段中设置电话号码的格式

淳于哲
2023-03-14

我希望在输入TextField时实时格式化电话号码。目标是在根据国家/地区形成电话号码的不同数字之间添加“分隔符”(空格、破折号、点...)。默认情况下,法国:06 23 65 14 85但也适用于其他国家/地区,如国际格式法语:33 6 23 65 14 85或德国国际格式:xx xxx xxx xx xxx

为此,我有一个监听器,当在TextField中添加新号码时,它会永久查找。然后,程序会负责检测正在输入的电话号码的格式,根据这一点,程序会使用我自己创建的“格式”来修改字符串的格式。

问题是,用户在重新格式化字符串的同时,光标在不断移动,如果用户删除或选择一个区域后再删除......每次,光标都移动到字符串的开头或结尾写起来很烦人。

您是否有一个解决方案来实时更改字符串的格式,同时确保光标位于正确的位置?目前我唯一的选择是lib,但这似乎很难维持,所以我宁愿自己做。否则,我必须等待图形组件上的非焦点,然后更改格式,但这不是我想要的。

我在下面为您提供了我的代码,请原谅,如果里面有一点法语,我有时会写一些。

import java.util.function.UnaryOperator;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.control.TextFormatter.Change;
import javafx.util.converter.IntegerStringConverter;

public class FormPhoneNumber {

    private StringProperty textPropertyFromComponent = new SimpleStringProperty();
    private TextField tf;
    private String separator;
    private String last = "";
    private int lastCaretPosition = 0;
    private ChangeListener<String> updateText;

    public FormPhoneNumber(TextField textField, String separator) {
        this.textPropertyFromComponent = textField.textProperty();
        this.tf = textField;


//On unfocus
//        tf.focusedProperty().addListener((ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) -> {
//            if (t1 == false) {
//                System.out.println("i");
//            }
//        });
        
        if (separator != null && !separator.isEmpty()) {
            this.separator = separator;
        } else {
            separator = " ";
        }
        checkNumberFormat();
    }

    private void checkNumberFormat() {

//Listener on write in the textfield
        updateText = (ObservableValue<? extends String> observable, String oldValue, String newValue) -> {
            if (newValue == null || newValue.isEmpty()) {
                return;
            }

//My customs formatters
            if (newValue.startsWith("+33")) {
//                System.out.println("FRANCE");
                String resultat = getPhoneNumberFormatted(newValue, "###-#-##-##-##-##");
                int caretPosition = tf.getCaretPosition();
                setResult(resultat, caretPosition, oldValue, newValue, 17);
            } else if (newValue.startsWith("+49")) {
//                System.out.println("ALLEMAGNE");
                String resultat = getPhoneNumberFormatted(newValue, "###-###-###-##-###");
                int caretPosition = tf.getCaretPosition();
                setResult(resultat, caretPosition, oldValue, newValue, 18);
            } else if (newValue.startsWith("+34")) {
//                System.out.println("ESPAGNE");
                String resultat = getPhoneNumberFormatted(newValue, "###-###-##-##-##");
                int caretPosition = tf.getCaretPosition();
                setResult(resultat, caretPosition, oldValue, newValue, 16);
            } else if (newValue.replaceAll(separator, "").startsWith("+3245") || newValue.replaceAll(separator, "").startsWith("+3249")) {
//                System.out.println("BELGIQUE GSM");
                String resultat = getPhoneNumberFormatted(newValue, "###-###-##-##-##");
                int caretPosition = tf.getCaretPosition();
                setResult(resultat, caretPosition, oldValue, newValue, 16);
            } else if (newValue.replaceAll(separator, "").startsWith("+322") || newValue.replaceAll(separator, "").startsWith("+323") || newValue.replaceAll(separator, "").startsWith("+329")) {
//                System.out.println("BELGIQUE AUTRE 1");
                String resultat = getPhoneNumberFormatted(newValue, "###-#-###-##-##");
                int caretPosition = tf.getCaretPosition();
                setResult(resultat, caretPosition, oldValue, newValue, 15);
            } else if (newValue.startsWith("+32")) {
//                System.out.println("BELGIQUE");
                String resultat = getPhoneNumberFormatted(newValue, "###-##-##-##-##");
                int caretPosition = tf.getCaretPosition();
                setResult(resultat, caretPosition, oldValue, newValue, 15);
            } else if (newValue.replaceAll(separator, "").startsWith("+3526")) {
//                System.out.println("LUXEMBOURG 1");
                String resultat = getPhoneNumberFormatted(newValue, "####-###-###-###");
                int caretPosition = tf.getCaretPosition();
                setResult(resultat, caretPosition, oldValue, newValue, 16);
            } else if (newValue.startsWith("+352")) {
//                System.out.println("LUXEMBOURG AUTRE");
                String resultat = getPhoneNumberFormatted(newValue, "####-##-##-##-##");
                int caretPosition = tf.getCaretPosition();
                setResult(resultat, caretPosition, oldValue, newValue, 16);
            } else if (newValue.startsWith("+377")) {
//                System.out.println("MONACO");
                String resultat = getPhoneNumberFormatted(newValue, "####-##-##-##-##");
                int caretPosition = tf.getCaretPosition();
                setResult(resultat, caretPosition, oldValue, newValue, 16);
            } else if (newValue.startsWith("+41")) {
//                System.out.println("SUISSE");
                String resultat = getPhoneNumberFormatted(newValue, "###-##-###-##-##");
                int caretPosition = tf.getCaretPosition();
                setResult(resultat, caretPosition, oldValue, newValue, 16);
            } else if (newValue.replaceAll(separator, "").startsWith("+390")) {
//                System.out.println("ITALIE FIXE");
                String resultat = getPhoneNumberFormatted(newValue, "###-##-####-####");
                int caretPosition = tf.getCaretPosition();
                setResult(resultat, caretPosition, oldValue, newValue, 16);
            } else if (newValue.replaceAll(separator, "").startsWith("+393")) {
//                System.out.println("ITALIE PORTABLE");
                String resultat = getPhoneNumberFormatted(newValue, "###-###-###-####");
                int caretPosition = tf.getCaretPosition();
                setResult(resultat, caretPosition, oldValue, newValue, 16);
            } else if (newValue.startsWith("+39")) {
//                System.out.println("ITALIE AUTRE");
                String resultat = getPhoneNumberFormatted(newValue, "###-##-####-####");
                int caretPosition = tf.getCaretPosition();
                setResult(resultat, caretPosition, oldValue, newValue, 16);
            } else if (newValue.startsWith("+376")) {
//                System.out.println("ANDORRE");
                String resultat = getPhoneNumberFormatted(newValue, "####-###-###-###");
                int caretPosition = tf.getCaretPosition();
                setResult(resultat, caretPosition, oldValue, newValue, 16);
            } else if (newValue.startsWith("+590")) {
//                System.out.println("GUADELOUPE");
                String resultat = getPhoneNumberFormatted(newValue, "####-###-##-##-##");
                int caretPosition = tf.getCaretPosition();
                setResult(resultat, caretPosition, oldValue, newValue, 17);
            } else if (newValue.startsWith("+596")) {
//                System.out.println("MARTINIQUE");
                String resultat = getPhoneNumberFormatted(newValue, "####-###-##-##-##");
                int caretPosition = tf.getCaretPosition();
                setResult(resultat, caretPosition, oldValue, newValue, 17);
            } else if (newValue.startsWith("+594")) {
//                System.out.println("GUYANE");
                String resultat = getPhoneNumberFormatted(newValue, "####-###-##-##-##");
                int caretPosition = tf.getCaretPosition();
                setResult(resultat, caretPosition, oldValue, newValue, 17);
            } else if (newValue.startsWith("+262")) {
//                System.out.println("REUNION ET MAYOTTE");
                String resultat = getPhoneNumberFormatted(newValue, "####-###-##-##-##");
                int caretPosition = tf.getCaretPosition();
                setResult(resultat, caretPosition, oldValue, newValue, 17);
            } else if (newValue.startsWith("+687")) {
//                System.out.println("NOUVELLE-CALEDONIE");
                String resultat = getPhoneNumberFormatted(newValue, "####-##-##-##");
                int caretPosition = tf.getCaretPosition();
                setResult(resultat, caretPosition, oldValue, newValue, 13);
            } else if (newValue.startsWith("+")) {
//                System.out.println("AUTRE - PAYS NON REFERENCE");
                String resultat = getPhoneNumberFormatted(newValue, "######################");
                int caretPosition = tf.getCaretPosition();
                setResult(resultat, caretPosition, oldValue, newValue, 22);
            } else if (newValue.length() >= 3) {
                if (Character.isDigit(newValue.charAt(0))) {
//                    System.out.println("France Nationnal");
                    String resultat = getPhoneNumberFormatted(newValue, "##-##-##-##-##");
                    int caretPosition = tf.getCaretPosition();
                    setResult(resultat, caretPosition, oldValue, newValue, 14);
                }
            }
        };
        textPropertyFromComponent.addListener(updateText);
    }

//My attempt to put the cursor in the right place, but VERY scary code
    private void setResult(String resultat, int caretPosition, String oldValue, String newValue, int maxLength) {
        Platform.runLater(() -> {
            if (resultat.length() <= maxLength && newValue != null && oldValue != null) {
                textPropertyFromComponent.set(resultat);
//                int diffAddLetter = newValue.length() - oldValue.length();
//                int diffRemLetter = oldValue.length() - newValue.length();
//                System.out.println("oldValue = " + oldValue);
//                System.out.println("newValue = " + newValue);
//                System.out.println("resultat = " + resultat);
//                System.out.println("test = " + last);
//                if (newValue.length() == maxLength) {
//                    if (!"".equals(last)) {
//                        tf.positionCaret(caretPosition + 1);
//                    }
//                } else if (diffAddLetter > 0) {
//                    System.out.println("diffAddLetter = " + diffAddLetter);
//                    System.out.println("lastCaretPosition = " + lastCaretPosition);
//                    System.out.println("caretPosition = " + caretPosition);
//                    if ("".equals(last)) {
//                        if (StringUtils.countMatches(oldValue, separator) < StringUtils.countMatches(newValue, separator)) {
//                            tf.positionCaret(caretPosition + 1);
//                        } else {
//                            tf.positionCaret(caretPosition);
//                        }
//                        System.out.println("a1");
//                    } else {
//                        tf.positionCaret(caretPosition + diffAddLetter);
//                        System.out.println("a2");
//                    }
//                    if (lastCaretPosition == caretPosition) {
//                        last = "";
//                    } else {
//                        last = oldValue;
//                    }
//                } else if (diffRemLetter > 0) {
//                    System.out.println("lastCaretPosition = " + lastCaretPosition);
//                    System.out.println("caretPosition = " + caretPosition);
//                    System.out.println("diffRemLetter = " + diffRemLetter);
//                    if ((lastCaretPosition == caretPosition || lastCaretPosition == (caretPosition - diffRemLetter)) && diffRemLetter > 1) {
//                        tf.positionCaret(caretPosition - diffRemLetter);
//                        System.out.println("r1");
//                    } else {
//                        System.out.println("caretPosition + diffRemLetter = " + (caretPosition - diffRemLetter));
////                        System.out.println("(newValue.substring(0, caretPosition) = " + (newValue.substring(0, caretPosition)));
//                        System.out.println("oldValue.substring(0, caretPosition) = " + oldValue.substring(0, caretPosition));
////                        System.out.println("newValue.substring(caretPosition) = " + newValue.substring(caretPosition +1));
//                        System.out.println("caretPosition = " + caretPosition);
//                        if (newValue.length() > caretPosition) {
//                            if (newValue.substring(0, caretPosition).equals(oldValue.substring(0, caretPosition)) && oldValue.endsWith(newValue.substring(caretPosition + 1)) && !"".equals(newValue.substring(caretPosition + 1)) && !String.valueOf(newValue.charAt(caretPosition - 1)).equals(separator)) {
//                                tf.positionCaret(caretPosition);
//                                System.out.println("r2");
//                            } else if (Character.isDigit(newValue.charAt(caretPosition - 1)) && Character.isDigit(newValue.charAt(caretPosition)) && diffRemLetter == 1) {
//                                tf.positionCaret(caretPosition);
//                                System.out.println("r5");
//                            } else {
//                                tf.positionCaret(caretPosition + 1);
//                                System.out.println("r3");
//                            }
//                        } else {
//                            System.out.println("r4");
//                            tf.positionCaret(lastCaretPosition);
//                        }
//                        last = oldValue;
//                    }
//                } else if (String.valueOf(resultat.charAt(caretPosition - 1)).equals(separator) && last.length() < resultat.length()) {
//                    tf.positionCaret(caretPosition + 1);
//                    System.out.println("s");
//                } else {
//                    tf.positionCaret(caretPosition);
//                    System.out.println("o");
//                }
//                if (resultat.length() >= caretPosition) {
//                    if (oldValue.replaceAll(separator, "").equals(newValue.replaceAll(separator, "")) && String.valueOf(resultat.charAt(caretPosition)).equals(separator)) {
//                        tf.positionCaret(caretPosition);
//                        System.out.println("c");
//                    }
//                }
//                lastCaretPosition = caretPosition;
            } else {
                textPropertyFromComponent.set(oldValue);
            }
        });
        textPropertyFromComponent.addListener(updateText);
    }

//Method to format the phone number
    private String getPhoneNumberFormatted(String phoneNumber, String format) {
        textPropertyFromComponent.removeListener(updateText);
        String vretour = "";
        if (phoneNumber.length() <= format.length()) {
            phoneNumber = phoneNumber.replaceAll("[^0-9+]", "");
            int index = findXDotPosition(format, phoneNumber.length());
            format = format.substring(0, index + 1);
            int indexCharArray = 0;
            for (char unChar : format.toCharArray()) {
                if ("#".charAt(0) == unChar) {
                    vretour = vretour + phoneNumber.toCharArray()[indexCharArray];
                    indexCharArray++;
                }
                if ("-".charAt(0) == unChar) {
                    vretour = vretour + separator;
                }
            }
        } else {
            vretour = phoneNumber;
        }
        return vretour;
    }

//Method to find a separator
    private static int findXDotPosition(String s, int separatorToFind) {
        int result = -1;
        char[] ca = s.toCharArray();
        for (int i = 0; i < ca.length; ++i) {
            if (ca[i] == '#') {
                --separatorToFind;
            }
            if (separatorToFind == 0) {
                return i;
            }
        }
        return result;
    }
}

我还提供了一些应用程序实际工作的屏幕截图。

https://i.goopics.net/Jl8aR.png https://i.goopics.net/RVvdZ.png

希望你能给我一个解决方案,提前感谢!

共有2个答案

鲍国兴
2023-03-14

非常感谢你的回答DaveB!它工作得非常好,我为您提供了最终代码:

package PhoneNumberTest;

import java.util.function.UnaryOperator;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.util.converter.DefaultStringConverter;
import org.apache.commons.lang3.StringUtils;

public class PhoneNumberFilter implements UnaryOperator<TextFormatter.Change> {

    private String separator = " ";
    private int length = 0;
    private TextField tf;

    private final String formatForFrance = "###-#-##-##-##-##";
    private final String formatForAllemagne = "###-###-###-##-###";
    private final String formatForEspagne = "###-###-##-##-##";
    private final String formatForBelgiqueGSM = "###-###-##-##-##";
    private final String formatForBelgiqueAutre = "###-#-###-##-##";
    private final String formatForBelgique = "###-##-##-##-##";
    private final String formatForLuxembourg = "####-###-###-###";
    private final String formatForLuxembourgAutre = "####-##-##-##-##";
    private final String formatForMonaco = "####-##-##-##-##";
    private final String formatForSuisse = "###-##-###-##-##";
    private final String formatForItalieFixe = "###-##-####-####";
    private final String formatForItaliePort = "###-###-###-####";
    private final String formatForItalieAutre = "###-##-####-####";
    private final String formatForAndorre = "####-###-###-###";
    private final String formatForGuadeloupe = "####-###-##-##-##";
    private final String formatForMartinique = "####-###-##-##-##";
    private final String formatForGuyane = "####-###-##-##-##";
    private final String formatForReunionMayotte = "####-###-##-##-##";
    private final String formatForNouvelleCaledonie = "####-##-##-##";
    private final String formatForAutre = "######################";
    private final String formatForFranceNationnal = "##-##-##-##-##";

    public PhoneNumberFilter(TextField textField, String separator) {
        this.tf = textField;
        if (separator != null && !separator.isEmpty()) {
            this.separator = separator;
        } else {
            this.separator = "";
        }
        TextFormatter<String> textFormatter = new TextFormatter(new DefaultStringConverter(), "", new PhoneNumberFilter());
        tf.setTextFormatter(textFormatter);
    }

    public PhoneNumberFilter() {
    }

    @Override
    public TextFormatter.Change apply(TextFormatter.Change change) {
        if (change.isContentChange()) {
            String resultat = "";
            handleBackspaceOverSpecialCharacter(change);
            int originalNewTextLength = change.getControlNewText().length();
            if (change.getControlNewText().startsWith("+33")) {
//            System.out.println("FRANCE");
                length = formatForFrance.length();
                resultat = getPhoneNumberFormatted(change.getControlNewText(), formatForFrance);
            } else if (change.getControlNewText().startsWith("+49")) {
//            System.out.println("ALLEMAGNE");
                length = formatForAllemagne.length();
                resultat = getPhoneNumberFormatted(change.getControlNewText(), formatForAllemagne);
            } else if (change.getControlNewText().startsWith("+34")) {
//            System.out.println("ESPAGNE");
                length = formatForEspagne.length();
                resultat = getPhoneNumberFormatted(change.getControlNewText(), formatForEspagne);
            } else if (change.getControlNewText().replaceAll(separator, "").startsWith("+3245") || change.getControlNewText().replaceAll(separator, "").startsWith("+3249")) {
//            System.out.println("BELGIQUE GSM");
                length = formatForBelgiqueGSM.length();
                resultat = getPhoneNumberFormatted(change.getControlNewText(), formatForBelgiqueGSM);
            } else if (change.getControlNewText().replaceAll(separator, "").startsWith("+322") || change.getControlNewText().replaceAll(separator, "").startsWith("+323") || change.getControlNewText().replaceAll(separator, "").startsWith("+329")) {
//            System.out.println("BELGIQUE AUTRE 1");
                length = formatForBelgiqueAutre.length();
                resultat = getPhoneNumberFormatted(change.getControlNewText(), formatForBelgiqueAutre);
            } else if (change.getControlNewText().startsWith("+32")) {
//            System.out.println("BELGIQUE");
                length = formatForBelgique.length();
                resultat = getPhoneNumberFormatted(change.getControlNewText(), formatForBelgique);
            } else if (change.getControlNewText().replaceAll(separator, "").startsWith("+3526")) {
//            System.out.println("LUXEMBOURG 1");
                length = formatForLuxembourg.length();
                resultat = getPhoneNumberFormatted(change.getControlNewText(), formatForLuxembourg);
            } else if (change.getControlNewText().startsWith("+352")) {
//            System.out.println("LUXEMBOURG AUTRE");
                length = formatForLuxembourgAutre.length();
                resultat = getPhoneNumberFormatted(change.getControlNewText(), formatForLuxembourgAutre);
            } else if (change.getControlNewText().startsWith("+377")) {
//            System.out.println("MONACO");
                length = formatForMonaco.length();
                resultat = getPhoneNumberFormatted(change.getControlNewText(), formatForMonaco);
            } else if (change.getControlNewText().startsWith("+41")) {
//            System.out.println("SUISSE");
                length = formatForSuisse.length();
                resultat = getPhoneNumberFormatted(change.getControlNewText(), formatForSuisse);
            } else if (change.getControlNewText().replaceAll(separator, "").startsWith("+390")) {
//            System.out.println("ITALIE FIXE");
                length = formatForItalieFixe.length();
                resultat = getPhoneNumberFormatted(change.getControlNewText(), formatForItalieFixe);
            } else if (change.getControlNewText().replaceAll(separator, "").startsWith("+393")) {
//            System.out.println("ITALIE PORTABLE");
                length = formatForItaliePort.length();
                resultat = getPhoneNumberFormatted(change.getControlNewText(), formatForItaliePort);
            } else if (change.getControlNewText().startsWith("+39")) {
//            System.out.println("ITALIE AUTRE");
                length = formatForItalieAutre.length();
                resultat = getPhoneNumberFormatted(change.getControlNewText(), formatForItalieAutre);
            } else if (change.getControlNewText().startsWith("+376")) {
//            System.out.println("ANDORRE");
                length = formatForAndorre.length();
                resultat = getPhoneNumberFormatted(change.getControlNewText(), formatForAndorre);
            } else if (change.getControlNewText().startsWith("+590")) {
//            System.out.println("GUADELOUPE");
                length = formatForGuadeloupe.length();
                resultat = getPhoneNumberFormatted(change.getControlNewText(), formatForGuadeloupe);
            } else if (change.getControlNewText().startsWith("+596")) {
//            System.out.println("MARTINIQUE");
                length = formatForMartinique.length();
                resultat = getPhoneNumberFormatted(change.getControlNewText(), formatForMartinique);
            } else if (change.getControlNewText().startsWith("+594")) {
//            System.out.println("GUYANE");
                length = formatForGuyane.length();
                resultat = getPhoneNumberFormatted(change.getControlNewText(), formatForGuyane);
            } else if (change.getControlNewText().startsWith("+262")) {
//            System.out.println("REUNION ET MAYOTTE");
                length = formatForReunionMayotte.length();
                resultat = getPhoneNumberFormatted(change.getControlNewText(), formatForReunionMayotte);
            } else if (change.getControlNewText().startsWith("+687")) {
//            System.out.println("NOUVELLE-CALEDONIE");
                length = formatForNouvelleCaledonie.length();
                resultat = getPhoneNumberFormatted(change.getControlNewText(), formatForNouvelleCaledonie);
            } else if (change.getControlNewText().startsWith("+")) {
//            System.out.println("AUTRE - PAYS NON REFERENCE");
                length = formatForAutre.length();
                resultat = getPhoneNumberFormatted(change.getControlNewText(), formatForAutre);
            } else if (change.getControlNewText().length() >= 3) {
                if (Character.isDigit(change.getControlNewText().charAt(0))) {
//                System.out.println("France Nationnal");
                    length = formatForFranceNationnal.length();
                    resultat = getPhoneNumberFormatted(change.getControlNewText(), formatForFranceNationnal);
                }
            } else {
                resultat = change.getControlNewText();
            }
            if (change.getControlText().length() == length && originalNewTextLength > length && length != 0) {
                change.setText(change.getControlText());
            } else {
                change.setText(resultat);
            }
            change.setRange(0, change.getControlText().length());
            int caretOffset = change.getControlNewText().length() - originalNewTextLength;
            change.setCaretPosition(change.getCaretPosition() + caretOffset);
            change.setAnchor(change.getAnchor() + caretOffset);
            return change;
        }
        return change;
    }

    private void handleBackspaceOverSpecialCharacter(TextFormatter.Change change) {
        if (change.isDeleted() && (change.getSelection().getLength() == 0)) {
            if (!Character.isDigit(change.getControlText().charAt(change.getRangeStart())) && !"+".equals(String.valueOf(change.getControlText().charAt(change.getRangeStart())))) {
                if (change.getRangeStart() > 0) {
                    change.setRange(change.getRangeStart() - 1, change.getRangeEnd() - 1);
                }
            }
        }
    }

    private String getPhoneNumberFormatted(String phoneNumber, String format) {
        if (phoneNumber.length() > length) {
            phoneNumber = phoneNumber.substring(0, length);
        }
        String vretour = "";
        if (phoneNumber.length() <= format.length()) {
            phoneNumber = phoneNumber.replaceAll("[^0-9+]", "");
            int index = findXDotPosition(format, phoneNumber.length());
            format = format.substring(0, index + 1);
            int indexCharArray = 0;
            for (char unChar : format.toCharArray()) {
                if ("#".charAt(0) == unChar) {
                    vretour = vretour + phoneNumber.toCharArray()[indexCharArray];
                    indexCharArray++;
                }
                if ("-".charAt(0) == unChar) {
                    vretour = vretour + separator;
                }
            }
        } else {
            vretour = phoneNumber;
        }
        return vretour;
    }

    private static int findXDotPosition(String s, int separatorToFind) {
        int result = -1;
        char[] ca = s.toCharArray();
        for (int i = 0; i < ca.length; ++i) {
            if (ca[i] == '#') {
                --separatorToFind;
            }
            if (separatorToFind == 0) {
                return i;
            }
        }
        return result;
    }
}

只需创建这样一个对象,即新的PhoneNumberFilter(tf,“”) (tf=TextField,第二个参数是不同电话号码之间的分隔符)。这将执行程序的其余部分,并将很好地重新格式化输入的数字。

我只有最后一个问题。当我两次单击电话号码的末尾时,或者当我尝试在电话号码的末尾写入时,当号码已经达到所指示的最大字符数时,我的光标会无缘无故向后移动1个槽口,并且我找不到强制光标停留在号码的最末端的方法。这正常吗?有解决方案吗?

席兴朝
2023-03-14

文本格式绝对是要走的路。您需要构建的是文本格式的过滤器组件。基本上,您可以将其视为击键处理器(也处理鼠标操作),所有低级的东西都已为您处理。您会得到一个TextFor事。更改传递给您的对象,您可以看到该更改将如何影响字段中的值,然后修改它、抑制它或让它通过。

因此,所有的格式都会立即发生,就在您键入时的文本字段中。

我做了一个来处理北美风格的电话号码,因为它比欧洲风格更有趣,因为它有括号和破折号。但是你可以适应它。

我采取的方法是从字符串中去掉所有格式字符,然后每次更改时重新格式化。这似乎比试图一个字符一个字符地摆弄它要容易得多。唯一棘手的部分是击球

public class PhoneNumberFilter implements UnaryOperator<TextFormatter.Change> {

@Override
public TextFormatter.Change apply(TextFormatter.Change change) {
    if (change.isContentChange()) {
        handleBackspaceOverSpecialCharacter(change);
        if (change.getText().matches("[0-9]*")) {
            int originalNewTextLength = change.getControlNewText().length();
            change.setText(formatNumber(change.getControlNewText()));
            change.setRange(0, change.getControlText().length());
            int caretOffset = change.getControlNewText().length() - originalNewTextLength;
            change.setCaretPosition(change.getCaretPosition() + caretOffset);
            change.setAnchor(change.getAnchor() + caretOffset);
            return change;
        } else {
            return null;
        }
    }
    return change;
}

private void handleBackspaceOverSpecialCharacter(TextFormatter.Change change) {
    if (change.isDeleted() && (change.getSelection().getLength() == 0)) {
        if (!Character.isDigit(change.getControlText().charAt(change.getRangeStart()))) {
            if (change.getRangeStart() > 0) {
                change.setRange(change.getRangeStart() - 1, change.getRangeEnd() - 1);
            }
        }
    }
}

private String formatNumber(String numbers) {
    numbers = numbers.replaceAll("[^\\d]", "");
    numbers = numbers.substring(0, Math.min(10, numbers.length()));
    if (numbers.length() == 0) {
        return "";
    }
    if (numbers.length() < 4) {
        return "(" + numbers;
    }
    if (numbers.length() < 7) {
        return numbers.replaceFirst("(\\d{3})(\\d+)", "($1)$2");
    }
    return numbers.replaceFirst("(\\d{3})(\\d{3})(\\d+)", "($1)$2-$3");
}

}

这里有一个小的测试应用程序。您可以看到,转换器只是“开箱即用”的默认转换器,因为它只是一个主要由数字组成的字符串:

public class PhoneNumberTest extends Application {

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

    @Override
    public void start(Stage primaryStage) {
        TextField textField = new TextField();
        TextFormatter<String> textFormatter = new TextFormatter(new DefaultStringConverter(), "", new PhoneNumberFilter());
        textField.setTextFormatter(textFormatter);
        Scene scene = new Scene(new VBox(textField), 300, 100);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}
 类似资料:
  • 问题内容: 一旦用户开始将电话号码键入此格式类型,并且我可以正常工作,我就在格式化文本文件中的文本,但是一旦我从服务器上获得了电话号码,我就这样得到了,所以请您告诉我如何编辑它我从服务器获得相同格式的文件吗? 输入开始后的代码: 问题答案: 用String中的字符进行操作不是很简单。您需要遵循以下条件: 斯威夫特2.1 雨燕2.0 代码将打印

  • 问题内容: 我一直在存储电话号码,所以我想在将电话号码打印为字符串时简单地添加连字符。 我尝试使用,但是不喜欢连字符。可能是因为它用于格式化十进制数字而不是long。 理想情况下,我也想在区号上加上括号。 正确的方法是什么? 问题答案: 这就是我最终这样做的方式: 我知道这不支持国际号码,但是我不是在编写“真实”应用程序,因此我对此并不担心。我只接受10个字符作为电话号码。我只是想以某种格式打印它

  • 问题内容: 我有一个数据库,其中包含数以百万计的免费格式的电话号码。即,UI不强制执行任何约束,并且用户正在键入他们想要的任何内容。 我正在寻找的是一种Java API,可以尽力将它们转换为一致的格式。理想情况下,API将采用自由文本值和国家/地区代码,并产生有效的国际电话号码或引发异常。 例如,系统中的电话号码可能类似于以下任何一项: 给定美国所在的国家/地区,API将为所有这些产生值“ +1(

  • 我目前使用phonenumbers包作为我的Django的UserCreationForm的电话号码字段的验证方法。在我当前的代码中,我使用get方法从其字段中检索电话号码,然后进行验证。如果输入的数字不存在,将弹出一个表单错误,并声明该数字不是一个国家的格式(在本例中,我使用的是新加坡)。请告诉我应该对我当前的代码做什么修改。 我希望输出验证phone字段中输入的电话号码,没有国家代码,只有8位

  • 当前正在处理一个文本字段,如果您输入您的号码,它会像这样更新: 1##-###-#### 12#-###-#### 不幸的是,通过控制台将输入“1234”转换为“123-4###########”是可行的,但当我按下更新的字符串“123-4###-#####”时,它会自动将光标部分替换到开始位置,并不断替换第一位数字。当更新文本框中的字符串时,是否有人可以帮助保存光标位置?这是我的更新代码。

  • 问题内容: 我想知道如何使用angularjs指令在输入字段中自动设置数字格式?在输入字段中输入6042919283时,我希望它显示为604-291-9283。 谢谢 问题答案: 您可以使用UI Utils遮罩。 它允许您定义允许的输入格式,并将为您处理验证以及格式设置