【问题标题】:Javafx: Updating a phone number textfield with hashtags and numbers liveJavafx:使用主题标签和数字实时更新电话号码文本字段
【发布时间】:2017-02-10 01:05:53
【问题描述】:

目前正在处理一个文本字段,如果你输入你的号码,它会更新它:

1##-###-####

12#-###-####

不幸的是,通过控制台将输入“1234”转换为“123-4##-####”是可行的,尽管当我推送更新的字符串“123-4##-#### " 它会自动将光标部分替换到开头,它将不断替换第一个数字。更新文本框中的字符串时,有人可以帮助保存光标位置吗?这是我的更新代码。

phoneField.textProperty().addListener((observable, oldValue, newValue) -> {
       Pattern p = Pattern.compile("-?\\d+");
       Matcher m = p.matcher(newValue);
       String result = "";
       String finalString = "";
       try {
           while (m.find()) {
               result = m.group();
           }
           int size = result.length();
           for(int i = 0; i < size; i++) {
               if(i == 3 || i == 6) finalString += "-";
               finalString += result.charAt(i);
           }
           for(int i = size; i < 10; i++) {
               if(i == 3 || i == 6) finalString += "-";
               finalString += "#";
           }
       } catch (Exception e) {
           finalString = "INVALID NUMBER";
       }
        phoneField.setText(finalString);
    });

【问题讨论】:

  • 也许phoneField. positionCaret(newValue.length()) ?
  • 不幸的是,这只是将我的插入符号设置到文本的末尾
  • @Nom 嘿,你试过我的解决方案了吗?

标签: java javafx javafx-2 javafx-8


【解决方案1】:

您不应该使用侦听器,因为您正在更改您正在侦听的属性,这意味着侦听器会被调用两次。实际上,将导致无限循环,除非 StringProperty 足够聪明,可以在新值等于旧值时避免触发更改。 (大多数 JavaBean 兼容类的行为都是这样的,但我不知道对这种行为有任何保证。)

为了限制 TextField 的行为,您通常希望使用 TextFormatter

private TextField createPhoneField() {
    TextField phoneField = new TextField();
    phoneField.setPrefColumnCount(12);

    TextFormatter<String> formatter =
        new TextFormatter<>(this::addPhoneNumberMask);
    phoneField.setTextFormatter(formatter);

    return phoneField;
}

private TextFormatter.Change addPhoneNumberMask(
                                TextFormatter.Change change) {

    // Ignore cursor movements, unless the text is empty (in which case
    // we're initializing the field).
    if (!change.isContentChange() &&
        !change.getControlNewText().isEmpty()) {

        return change;
    }

    String text = change.getControlNewText();
    int start = change.getRangeStart();
    int end = change.getRangeEnd();

    int anchor = change.getAnchor();
    int caret = change.getCaretPosition();

    StringBuilder newText = new StringBuilder(text);

    int dash;
    while ((dash = newText.lastIndexOf("-")) >= start) {
        newText.deleteCharAt(dash);
        if (caret > dash) {
            caret--;
        }
        if (anchor > dash) {
            anchor--;
        }
    }

    while (newText.length() < 3) {
        newText.append('#');
    }
    if (newText.length() == 3 || newText.charAt(3) != '-') {
        newText.insert(3, '-');
        if (caret > 3 || (caret == 3 && end <= 3 && change.isDeleted())) {
            caret++;
        }
        if (anchor > 3 || (anchor == 3 && end <= 3 && change.isDeleted())) {
            anchor++;
        }
    }

    while (newText.length() < 7) {
        newText.append('#');
    }
    if (newText.length() == 7 || newText.charAt(7) != '-') {
        newText.insert(7, '-');
        if (caret > 7 || (caret == 7 && end <= 7 && change.isDeleted())) {
            caret++;
        }
        if (anchor > 7 || (anchor == 7 && end <= 7 && change.isDeleted())) {
            anchor++;
        }
    }

    while (newText.length() < 12) {
        newText.append('#');
    }

    if (newText.length() > 12) {
        newText.delete(12, newText.length());
    }

    text = newText.toString();
    anchor = Math.min(anchor, 12);
    caret = Math.min(caret, 12);

    change.setText(text);
    change.setRange(0, change.getControlText().length());
    change.setAnchor(anchor);
    change.setCaretPosition(caret);

    return change;
}

【讨论】:

    【解决方案2】:

    我对您的代码做了一些更改。 首先,您应该附加匹配结果以获得正确的值 - 我已经使用了 StringBuilder.append() 。然后,我更改了编译模式,否则将无法正确处理输入。

    phoneField.textProperty().addListener((observable, oldValue, newValue) -> {
        Pattern p = Pattern.compile("\\d+");
        Matcher m = p.matcher(newValue);
        StringBuilder result = new StringBuilder();
        String finalString = "";
        try {
            while (m.find()) {
                result.append(m.group());
            }
            int size = result.length();
            for (int i = 0; i < size; i++) {
                if (i == 3 || i == 6) finalString += "-";
                finalString += result.charAt(i);
            }
            for (int i = size; i < 9; i++) {
                if (i == 3 || i == 6) finalString += "-";
                finalString += "#";
            }
        } catch (Exception e) {
            finalString = "INVALID NUMBER";
        }
        phoneField.setText(finalString);
    });
    

    注意,可能值得为字段添加长度检查。

    【讨论】:

    • 这已经过时了(至少从 fx8 开始,在一些更新版本中,比如 u40 左右,忘记了确切的版本)并且由于VGR's answer 中列出的原因而气馁 - 这也有适当的解决方案:)跨度>
    猜你喜欢
    • 2016-03-29
    • 2016-08-30
    • 2020-03-13
    • 1970-01-01
    • 2018-07-13
    • 1970-01-01
    • 1970-01-01
    • 2014-04-27
    • 2010-12-19
    相关资源
    最近更新 更多