如何将掩码格式应用于TextField?

时间:2012-12-05 20:41:56

标签: javafx-2

我正在创建一些表单,我需要为某些字段创建掩码和验证。

它是否在JavaFX中实现?

8 个答案:

答案 0 :(得分:10)

mask的例子。

使用:

<MaskField mask="+7(DDD)DDD-DDDD"/>
<MaskField mask="AA DDD AAA" placeholder="__ ### ___"/>

答案 1 :(得分:2)

限制来自Richard's fxexperience post的输入:

TextField field = new TextField() {
    @Override public void replaceText(int start, int end, String text) {
        // If the replaced text would end up being invalid, then simply
        // ignore this call!
        if (!text.matches("[a-z]")) {
            super.replaceText(start, end, text);
        }
    }

    @Override public void replaceSelection(String text) {
        if (!text.matches("[a-z]")) {
            super.replaceSelection(text);
        }
    }
};

如果您想创建使用遮罩并创建自己的控件,请查看Richard's MoneyField,其中还包括示例项目和来源。沿着相同的行,有一些控件可以在fxexperience repository中将输入重写为整数,双打或格式化的网页颜色(例如#rrggbb)。所有这些都遵循一个共同的主题,它们是子类Control,提供一些属性来获取和设置定义公共接口,然后还定义一个私有后备皮肤,它根据通过设置的值设置UI的呈现。公共界面。

答案 2 :(得分:2)

  

注意:这仅适用于JRE 1.8.0_25或更低版本。对于JRE 1.8.0_48或0_51,在每个字符输入后,插入符号位置始终设置为0.

不,这在标准JavaFX中没有实现。你需要使用一些库或自己动手。

这是我对文本字段的静态掩码的实现。它适用于日期,电话和其他类型的静态蒙版:

/**
 * Adds a static mask to the specified text field.
 * @param tf  the text field.
 * @param mask  the mask to apply.
 * Example of usage: addMask(txtDate, "  /  /    ");
 */
public static void addMask(final TextField tf, final String mask) {
    tf.setText(mask);
    addTextLimiter(tf, mask.length());

    tf.textProperty().addListener(new ChangeListener<String>() {
        @Override
        public void changed(final ObservableValue<? extends String> ov, final String oldValue, final String newValue) {
            String value = stripMask(tf.getText(), mask);
            tf.setText(merge(value, mask));
        }
    });

    tf.setOnKeyPressed(new EventHandler<KeyEvent>() {
        @Override
        public void handle(final KeyEvent e) {
            int caretPosition = tf.getCaretPosition();
            if (caretPosition < mask.length()-1 && mask.charAt(caretPosition) != ' ' && e.getCode() != KeyCode.BACK_SPACE && e.getCode() != KeyCode.LEFT) {
                tf.positionCaret(caretPosition + 1);
            }
        }
    });
}

static String merge(final String value, final String mask) {
    final StringBuilder sb = new StringBuilder(mask);
    int k = 0;
    for (int i = 0; i < mask.length(); i++) {
        if (mask.charAt(i) == ' ' && k < value.length()) {
            sb.setCharAt(i, value.charAt(k));
            k++;
        }
    }
    return sb.toString();
}

static String stripMask(String text, final String mask) {
    final Set<String> maskChars = new HashSet<>();
    for (int i = 0; i < mask.length(); i++) {
        char c = mask.charAt(i);
        if (c != ' ') {
            maskChars.add(String.valueOf(c));
        }
    }
    for (String c : maskChars) {
        text = text.replace(c, "");
    }
    return text;
}

public static void addTextLimiter(final TextField tf, final int maxLength) {
    tf.textProperty().addListener(new ChangeListener<String>() {
        @Override
        public void changed(final ObservableValue<? extends String> ov, final String oldValue, final String newValue) {
            if (tf.getText().length() > maxLength) {
                String s = tf.getText().substring(0, maxLength);
                tf.setText(s);
            }
        }
    });
}

另见: JavaFX 2.2 TextField maxlength

答案 3 :(得分:2)

我有同样的需求。我创建了这个字段,称为SpecialTextField,并推入GitHub。那里也有例子。希望这有帮助。

答案 4 :(得分:1)

默认情况下由当前的javafx-2平台提供支持 - 否,但通过this link,它有许多见解和示例代码,用于javaFX中的表单验证

答案 5 :(得分:0)

public class NumberTextField extends TextField {
    private int maxLenght;

    public NumberTextField(int maxLenght) {
        super();
        this.maxLenght = maxLenght;
    }

    @Override
    public void replaceText(int start, int end, String text) {
        if (validate(text)) {
            super.replaceText(start, end, text);
        }
    }

    @Override
    public void replaceSelection(String text) {
        if (validate(text)) {
            super.replaceSelection(text);
        }
    }

    private boolean validate(String text) {
        if (this.getText() != null) {
        }
        boolean status = ("".equals(text) || text.matches("[0-9]"));
        if (this.getText() == null) {
            return status;
        } else {
            return (status && this.getText().length() < maxLenght);
        }
    }
}

答案 6 :(得分:0)

在某些情况下,我会验证text属性:

myTextField
    .textProperty()
    .addListener(
    (obs, oldVal, newVal) -> 
        { 
            if(!newVal.matches("\\d+"))
                textField.setText(oldV);
        });

不走运:textField.setText(oldV);将再次输入相同的功能,如果oldVal匹配则不必要地进行测试。

如果TextField在将此侦听器添加到TextField之前变为不匹配的值,则输入不匹配的新值将导致循环!!!

为避免这种情况,写一下会更安全:

String acceptableValue = "0";
myTextField
    .textProperty()
    .addListener(
    (obs, oldVal, newVal) -> 
        { 
            if(!newVal.matches("\\d+"))
                textField.setText(oldVal.matches("\\d+") ? oldV : acceptableValue);
        });

答案 7 :(得分:0)

我写了一个扩展TextField并应用蒙版的类。

package com.model;

import java.text.NumberFormat;
import java.util.Locale;

/**
 * ATENTION
 * DO NOT FORGUET TO IMPORT IN FXML   
 * <?import com.view.TextFieldMoney?>
 * 
 * */

import javafx.scene.control.TextField;

public class TextFieldMoney extends TextField {
    private int maxlength;
    private String valor = "";

    public TextFieldMoney() {
        this.maxlength = 11;
    }

    public void setMaxlength(int maxlength) {
        this.maxlength = maxlength;
    }

    @Override
    public void replaceText(int start, int end, String text) {
        // Delete or backspace user input.
        if (getText() == null || getText().equalsIgnoreCase("")) {
            valor = "";
        }
        if (text.equals("")) {
            super.replaceText(start, end, text);
        } else{


            text = text.replaceAll("[^0-9]", "");
            valor += text;

            super.replaceText(start, end, text);
            if (!valor.equalsIgnoreCase(""))
                setText(formata(valor));
        }
    }

    @Override
    public void replaceSelection(String text) {
        // Delete or backspace user input.
        if (text.equals("")) {
            super.replaceSelection(text);
        } else if (getText().length() < maxlength) {
            // Add characters, but don't exceed maxlength.
            // text = MascaraFinanceira.show(text);
            if (text.length() > maxlength - getText().length()) {
                // text = MascaraFinanceira.show(text);
                text = text.substring(0, maxlength - getText().length());
            }
            super.replaceSelection(text);
        }
    }

    /*
     *Return the number without money mask
     **/

    public String getCleanValue(){
        String cleanString = getText().replaceAll("[^0-9]", "");
        Double cleanNumber = new Double(cleanString);
        return String.valueOf(cleanNumber/100);
    }

    private String formata(Double valor) {
        Locale locale = new Locale("pt", "BR");
        NumberFormat nf = NumberFormat.getInstance(locale);
        nf.setMaximumFractionDigits(2);
        nf.setMinimumFractionDigits(2);

        return nf.format(valor);
    }

    public String formata(String valor) {
        double v = new Double(valor);
        return formata(v/100);
    }

}

在FXML中

 <TextField fx:id="valorTextField" GridPane.columnIndex="2" GridPane.rowIndex="2" />

 <TextFieldMoney fx:id="valorTextField" GridPane.columnIndex="2" GridPane.rowIndex="2" />