Заставить JTextField принимать смешанные строки, чтобы documentFIlter разрешал только цифры

У меня необычная проблема, что-то работает слишком хорошо. Я написал DocumentFilter ведьму, позволяющую пользователю вводить только числа, DocumentFilter добавить тире в нужное место во время записи. Таким образом, inJTextField отображается дата, например: "2016-05-01". Проблема в том, что JTextField не всегда заполняется пользователем, иногда его должна задавать программа. Но когда я использую код setText("2016-05-01"), он не отображается должным образом, все тире исчезли. Как заставить его работать? Я попытался изменить DocumentFilter, чтобы разрешить тире, но это вызвало проблемы во многих других местах. Я, вероятно, закончу тем, что напишу еще один DocumentFilter только для этого, но, может быть, есть другой способ? Можно ли добавить JTextField char к char ? Есть ли способ включить или выключить DocumentFilter, или можно грамотно изменить DocumentFilter, чтобы он не давился в других местах и ​​работал и здесь? Ниже часть кода для DocumentFilter

  public void replace(FilterBypass fb, int offs, int length, String str,
    AttributeSet a) throws BadLocationException {

if (str == null || str.equals(""))
{
    super.replace(fb, offs, length, str, a); 
}
else
{
    StringBuffer buffer = new StringBuffer(str);
    for (int i = buffer.length() - 1; i >= 0; i--)
    {
    char ch = buffer.charAt(i);
    if (!Character.isDigit(ch))
    {
        buffer.deleteCharAt(i);
    }
    }

    str = buffer.toString();
    //sign and sign2 is char number were separator(sep) is written 
    if (fb.getDocument().getLength() + str.length() == sign)
    {
    str = str + sep;
    }
    if (fb.getDocument().getLength() + str.length() == sign2)
    {
    str = str + sep;
    }


    if ((fb.getDocument().getLength() + str.length() - length) <= maxCharacters)
    super.replace(fb, offs, length, str, a);
    else
    Toolkit.getDefaultToolkit().beep();
}

person Majlena    schedule 20.05.2016    source источник
comment
Вы пробовали setText("20160501") ?   -  person Titus    schedule 20.05.2016
comment
Да, это дает тот же результат, что и 2016-05-01. В обоих случаях показывает 20160501   -  person Majlena    schedule 20.05.2016


Ответы (1)


Вы можете сделать что-то вроде этого:

@Override
public void replace(FilterBypass fb, int offs, int length, String str, AttributeSet a) throws BadLocationException {
    if (str == null || str.equals("")) {
        super.replace(fb, offs, length, str, a);
    } else {
        // check if 'str' contains 8 digits
        if (str.matches("^\\d{8}$")) {
            // add the dashes
            super.replace(fb, offs, length, str.replaceAll("(\\d{4})(\\d{2})(\\d{2})", "$1-$2-$3"), a);
        } else {
            StringBuffer buffer = new StringBuffer(str);
            for (int i = buffer.length() - 1; i >= 0; i--) {
                char ch = buffer.charAt(i);
                if (!Character.isDigit(ch)) {
                    buffer.deleteCharAt(i);
                }
            }

            str = buffer.toString();
            // sign and sign2 is char number were separator(sep) is written
            if (fb.getDocument().getLength() + str.length() == sign) {
                str = str + sep;
            }
            if (fb.getDocument().getLength() + str.length() == sign2) {
                str = str + sep;
            }

            if ((fb.getDocument().getLength() + str.length() - length) <= maxCharacters)
                super.replace(fb, offs, length, str, a);
            else
                Toolkit.getDefaultToolkit().beep();
        }
    }
}

и установите текст, используя это:

textField.setText("20160420");
person Titus    schedule 20.05.2016