How to apply mask formatting to TextField?

2019-02-12 15:50发布

I am creating some forms and I need to create masks and validation for some fields.

Is it implemented in anyway in JavaFX?

标签: javafx-2
8条回答
我欲成王,谁敢阻挡
2楼-- · 2019-02-12 16:30

I wrote a class that extends the TextField and apply the mask.

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);
    }

}

And in the FXML where is

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

put

 <TextFieldMoney fx:id="valorTextField" GridPane.columnIndex="2" GridPane.rowIndex="2" />
查看更多
乱世女痞
3楼-- · 2019-02-12 16:36

My example of the mask.

Using:

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

etc

查看更多
ら.Afraid
4楼-- · 2019-02-12 16:41

Restricting input from 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);
        }
    }
};

If you want to create your use a mask and create your own control, take a look at Richard's MoneyField, which also includes a sample project and source. Along the same lines there are controls to restict input to Integers, Doubles or formatted web colors (e.g. #rrggbb) in the fxexperience repository. All of these follow a common theme where they subclass Control, provide some properties to be get and set which define the public interface and then also define a private backing skin which handles rendering of the UI based on the values set through the public interface.

查看更多
趁早两清
5楼-- · 2019-02-12 16:45

I had the same needs. I created this field, called it SpecialTextField, and pushed into GitHub. Example also there. Hope this help.

查看更多
Anthone
6楼-- · 2019-02-12 16:47
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);
        }
    }
}
查看更多
该账号已被封号
7楼-- · 2019-02-12 16:48

NOTE: this only works correctly with JRE 1.8.0_25 or lower. With JRE 1.8.0_48 or 0_51, the caret position is always set to 0 after each character input.

No, this is not implemented in standard JavaFX. You need to use some library or do it yourself.

This is my implementation of static mask for text fields. It works for date, phone and other types of static masks:

/**
 * 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);
            }
        }
    });
}

See also: JavaFX 2.2 TextField maxlength

查看更多
登录 后发表回答