JTextField の入力制限機能サンプルソースコード (Example Validation：1から30までの数値)

# 注意
lowerLimit と upperLimit の値を変更して流用して下さい。
どの文字を打とうとしても半角数字1~30しか入力できません。
DocumentFilterは内部クラスを作った方が良いです。
※おそらく、このアルゴリズムは他の言語に応用可能。

# ソースコード

```Java:Example
JTextField textField = new JTextField();
((PlainDocument)textField.getDocument()).setDocumentFilter(new DocumentFilter() {
    /**
     * 数値入力時、1から30までに制限
     * @param fb
     * @param offset カーソル位置
     * @param length 置換文字数
     * @param text 置換文字列
     * @param attrs fb.getDocument().getDefaultRootElement().getAttributes()と同じ
     */
    @Override 
    public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs)
      throws BadLocationException
        int lowerLimit = 1;
        int upperLimit = 30;

        int valueInput = 0;
        try {
            valueInput = Integer.parseInt(text);
        } catch(Exception ex) {
            // 入力値が数値以外、入力不可
            return;
        }
        // 入力値が全角数字の場合、半角数値に自動変換
        text = String.valueOf(valueInput);
        // 元々１文字も入力されていない場合
        if(fb.getDocument().getLength() == 0) {
            // 1～9の文字のみ入力可能
            if(valueInput != 0) {
                super.insertString(fb, offset, text, attrs);
            }
            return;
        }

        // 元々文字が入力されていた場合
        } else {
            // 入力後の値の算出
            String strAlready = fb.getDocument.getText(0, fb.getDocument().getLength());
            int valueAlready = Integer.parseInt(strAlready);
            int valueTotal = 0;
            if(offset == 0) {
                // Input Left
                valueTotal = (int) (valueInput * Math.pow(10, strAlready.length()) + valueAlready);
            } else if(offset == strAlready.length()) {
                // Input Right
                valueTotal = (int) (valueAlready * 10 + valueInput);
            } else {
                // Input Mid
                int valueLeft  = (int) ( Integer.parseInt(strAlready.substring(0, offset))
                                        * Math.pow(10, strAlready.length()-offset+1) );
                int valueAdd   = (int) ( valueInput * Math.pow(10, strAlready.length()-offset) );
                int valueRight = Integer.parseInt( strAlready.substring(offset, strAlready.length()) );
                valueTotal = valueLeft + valueAdd + valueRight;
            }
            // 入力値を1から30までに制限
            if(valueTotal > upperLimit) {
                // 入力後の値 > 最大値
                super.remove(fb, 0, strAlready.length()); // 元の文字をすべて削除
                if(valueInput != 0) {
                    super.insertString(fb, 0, String.valueOf(valueInput), attrs); // 入力値設定
                } else {
                    super.insertString(fb, 0, String.valueOf(upperLimit), attrs); // 最大値設定
                }
            } else if(valueTotal < lowerLimit) {
                super.replace(fb, 0, strAlready.length(), String.valueOf(lowerLimit), attrs); // 最小値設定
            } else {
                super.replace(fb, offset, length, text, attrs); // 本来の値入力時のreplaceメソッド処理呼び出し
            }
        }
    }

    /**
     * 値削除時、1より小さい値を入力不可に制限
     * @param fb
     * @param offset カーソル位置
     * @param length 削除文字数
     */
    @Override 
    public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
        int lowerLimit = 1;

        String strBefore = fb,getDocument.getText(0, fb.getDocument().getLength());
        String strAfter  = strBefore.substring(0, offset)
                           + strBefore.substring(offset+length, fb.getDocument().getLength());
        int afterValue = 0;
        try {
            afterValue = Integer.parseInt(strAfter);
        } catch(Exception ex) {
            // 入力値制御をしているため、エラーが起きるはずがない。
        }
        // 1より小さい値を設定不可
        if(strAfter.length() == 0 || afterValue < lowerLimit) {
            // 未入力や最小値より小さい値を設定した場合、最小値を設定
            super.replace(fb, 0, strBefore.length(), String.valueOf(lowerLimit), fb.getDocument().getDefaultRootElement().getAttributes());
        } else {
           // 本来の値削除時のremoveメソッド処理呼び出し
           super.remove(fb, offset, length);
        }
    }
});
```

# これを書いた理由
どこにも書いていなかったから。