2012-04-17 5 views
0

私は、入力として長くかかるJTextFieldのTextValueChangedハンドラを書いています。ユーザは、0とLong.MAXの間の有効な値を入力するだけで済みます。ユーザーが無効な文字を入力すると、JTextFieldの値が常に有効な長さになるように、ユーザーは無効な文字を入力する必要があります。クリーナーはJTextField入力を「サニタイズ」しますか?

私の現在のコードはこのように見えますが、醜いようです。外部のlib(Apache Commonsを含む)がない場合、これを行うためのよりクリーンで簡単な方法がありますか?

public void textValueChanged(TextEvent e) { 
    if (e.getSource() instanceof JTextField) { 
     String text = ((JTextField) e.getSource()).getText(); 
     try { 
      // Try to parse cleanly 
      long longNum = Long.parseLong(text); 
      // Check for < 1 
      if (longNum < 1) throw new NumberFormatException(); 
      // If we pass, set the value and return 
      setOption("FIELDKEY", longNum); 
     } catch (NumberFormatException e1) { 
      // We failed, so there's either a non-numeric or it's too large. 
      String s = ((JTextField) e.getSource()).getText(); 
      // Strip non-numeric characters 
      s = s.replaceAll("[^\\d]", ""); 
      long longNum = -1; 
      if (s.length() != 0) { 
       /* Really ugly workaround for the fact that a 
       * TextValueChanged event can capture more than one 
       * keystroke at a time, if it's typed fast enough, 
       * so we might have to strip more than one 
       * character. */ 
       Exception e3; 
       do { 
        e3 = null; 
        try { 
         // Try and parse again 
         longNum = Long.parseLong(s); 
        } catch (NumberFormatException e2) { 
         // We failed, so it's too large. 
         e3 = e2; 
         // Strip the last character and try again. 
         s = s.substring(0, s.length() - 1); 
        } 
        // Repeat 
       } while (e3 != null); 
      } 
      // We parsed, so add it (or blank it if it's < 1) and return. 
      setOption("FIELDKEY", (longNum < 1 ? 0 : longNum)); 
     } 
    } 
} 

フィールドは常にちょうどそのコールに渡し、「ストア」にその値が、getOptionコマンド(キー)呼び出しから再作成されます。

+1

代わりに 'JFormattedTextField'を使用すると何が問題になりますか? – user1329572

+0

私はそれをすることができましたが、それは私の好きなものとは一致しません。フォーカスが失われた場合は、変更を失い、以前に保存したテキスト(望ましくない)に戻すか、無効なテキストを保存します(これも不要です)。 この動作を強制するには、私はそれをオーバーライドして、別のイベントでいくつかのコードを書かなければなりません。 – Charles

+0

'JFormattedTextField'の問題は、あなたが好きなものを入力できることです。テキストフィールドを終了して初めて、検証が行われます。 –

答えて

6

DocumentFilterはあなたのために良い解決策である使用することができます中に使用することができますフロートのためにこれを持っています場合。

The Definitive Guide to Java Swing John Zukowskiの542-546ページには、整数範囲を制限するためのカスタムドキュメントフィルタを示す優れた例があります。

カスタムDocumentFilterを提供すると、コメントの1つで指定したように、コピー/ポーズ時に不要な文字を取り除く必要があります。

+0

私はDocumentFilterを少し見て、私はそれが契約破りだと思うと思う何かを見たと思った。私はそれに精通しているスーパーではないので、私は間違っていた可能性が完全に可能です。私はもう一度見て、ありがとう。 – Charles

+0

Zukowskiは次のように述べています。Documentのカスタムサブクラスを作成することはできますが、ドキュメントを変更したくないので、オブジェクト指向のアプローチはフィルタを作成することです。モデルへの入力を制限したいだけです。 – 01es

+0

+1書籍参照のため。 –

0

私はあなたが長い

class DoubleTextDocument extends PlainDocument { 
    public void insertString(int offs, String str, AttributeSet a) 
      throws BadLocationException { 
     if (str == null) 
      return; 
     String oldString = getText(0, getLength()); 
     String newString = oldString.substring(0, offs) + str 
       + oldString.substring(offs); 
     try { 
      Float.parseFloat(newString + "0"); 
      super.insertString(offs, str, a); 
     } catch (NumberFormatException e) { 
     } 
    } 
} 

とあなたの拡張JTextFieldあなたは

@Override

protected Document createDefaultModel() { 
    return new DoubleTextDocument(); 
} 
+0

私がDocument実装で持っていた主な問題は、私が好きなようにうまく動作しないことです。複数の文字が追加され、無効な文字が少数しかない場合は、無効な文字を消去するのではなく、すべての文字を使用して元の安全な値に戻します。 これまで言われていたのは、今まで考えていた次善の選択肢です。 私は、本質的に私が嘘をついているもののリファクタリングされ、より良い考えられたバージョンである何かを持っていることを望んでいます。 – Charles

+0

これで、英数字テキストのコピー貼りが行われる場合、数値部分のみが –

+0

とみなされる必要があるシナリオが必要です。申し訳ありませんが、私はそれがメインポストの制約だと指定するべきでした。 – Charles

関連する問題