2017-08-31 9 views
1

ユーザが特定のTextFieldにdouble値のを入力する方法を教えてください。JavaFXのTextFieldに二重入力を強制するには?

私が見つけたのはsolution for integersです。私はそれをダブルに使うことはできません。ダブルスのためには"\\d*""[^\\d]"の代わりに何を書くべきですか?

textField.textProperty().addListener(new ChangeListener<String>() { 
    @Override 
    public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) { 
     if (!newValue.matches("\\d*")) { 
      textField.setText(newValue.replaceAll("[^\\d]", "")); 
     } 
    } 
}); 
+0

リスナーを使用しないでください。 textプロパティの他のオブザーバは、無効な入力が元に戻される前にそれを見ます。代わりに 'TextFormatter'を使用してください。 –

答えて

4

リスナーを使用して、無効な値が動作するユーザーによって入力された場合、有効な値に戻すのアプローチがありますが、テキストフィールドのtextProperty上の他のリスナーを持っている場合、それは問題を作成することができます。それらのリスナーは無効な値と有効な値を観察するため、無効な値を除外することを知る必要があります。

より良い方法は、TextFormatterを使用することです。 TextFormatterは、2つのことを行うことができます。

  1. は拒否、または変更できる「フィルター」を定義し、TextFieldのテキストに加えた変更は、
  2. は、変換する方法を定義し、 『コンバータ』を、定義あなたのケースでは、特定のタイプの値(例えば、Double)の値との間のテキスト

適切なフィルタを定義するのは難しい場合があります。ユーザーが妥当な編集を許可したい場合です。つまり、ユーザーが編集中にテキストが無効な状態になっている可能性があります。例えばたとえ有効な値ではないとしても、テキストフィールドを完全に空にすることをお勧めします。 (そうでなければ、例えば "1"から "2"に変更したい場合、ユーザにとっては迷惑になります)。同様に、 " - "や "。"などのようなものを許可したいでしょう。

ここに例です。フィルタは、必要に応じてフィルタに渡された変更を修正し、nullを返して変更を完全に拒否することができます。この例では、テキストが有効な編集状態を表しているかどうかを単純にチェックし、そうでない場合は変更をそのまま返し、そうでない場合は変更を返します。フォーマッタは、フィルタによって許可されたテキストを処理し、それをダブルに変換する必要があります。ここで不完全なものはゼロとして表されます。

Pattern validEditingState = Pattern.compile("-?(([1-9][0-9]*)|0)?(\\.[0-9]*)?"); 

UnaryOperator<TextFormatter.Change> filter = c -> { 
    String text = c.getControlNewText(); 
    if (validEditingState.matcher(text).matches()) { 
     return c ; 
    } else { 
     return null ; 
    } 
}; 

StringConverter<Double> converter = new StringConverter<Double>() { 

    @Override 
    public Double fromString(String s) { 
     if (s.isEmpty() || "-".equals(s) || ".".equals(s) || "-.".equals(s)) { 
      return 0.0 ; 
     } else { 
      return Double.valueOf(s); 
     } 
    } 


    @Override 
    public String toString(Double d) { 
     return d.toString(); 
    } 
}; 

TextFormatter<Double> textFormatter = new TextFormatter<>(converter, 0.0, filter); 
TextField textField = new TextField(); 
textField.setTextFormatter(textFormatter); 

正規表現を必要に応じてさらに複雑にすることができます。グループ化文字("1,000.0")、ローカライズ(ロケールに適している場合は"1.003,14159")、科学表記のような表現("6.022E23"など)をサポートしたり、最小値や最大値などを適用することができます。ユーザーがテキスト内の任意の場所に-と入力すると、番号の記号が反転するように変更を変更します。 (その種の機能については、TextFormatter.Change documentationを参照してください。)

ObjectProperty<Double> valueProperty()を持つフォーマッタから直接(コンバータが提供する)double値を取得して設定できます。あなたのようなことをすることができます

// update text field: 
double value = ... ; 
textFormatter.setValue(value); 

// listen for changes in double value represented in text field 
// Listener will be invoked when the user commits an edit: 

textFormatter.valueProperty().addListener((ObservableValue<? extends Double> obs, Double oldValue, Double newValue) -> { 
    System.out.println("User entered value: "+newValue.doubleValue()); 
}); 

ここはSSCCEです。 2番目のテキストフィールドはちょうどそこにあるので、フォーカスを別のコントロールに移動する効果を見ることができます(値が変更されると、値を "コミット"し、テキストフォーマッタでリスナーを呼び出します。プレス入力)。

import java.util.function.UnaryOperator; 
import java.util.regex.Pattern; 

import javafx.application.Application; 
import javafx.beans.value.ObservableValue; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.TextField; 
import javafx.scene.control.TextFormatter; 
import javafx.scene.layout.VBox; 
import javafx.stage.Stage; 
import javafx.util.StringConverter; 

public class NumericTextField extends Application { 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
     Pattern validEditingState = Pattern.compile("-?(([1-9][0-9]*)|0)?(\\.[0-9]*)?"); 

     UnaryOperator<TextFormatter.Change> filter = c -> { 
      String text = c.getControlNewText(); 
      if (validEditingState.matcher(text).matches()) { 
       return c ; 
      } else { 
       return null ; 
      } 
     }; 

     StringConverter<Double> converter = new StringConverter<Double>() { 

      @Override 
      public Double fromString(String s) { 
       if (s.isEmpty() || "-".equals(s) || ".".equals(s) || "-.".equals(s)) { 
        return 0.0 ; 
       } else { 
        return Double.valueOf(s); 
       } 
      } 


      @Override 
      public String toString(Double d) { 
       return d.toString(); 
      } 
     }; 

     TextFormatter<Double> textFormatter = new TextFormatter<>(converter, 0.0, filter); 
     TextField textField = new TextField(); 
     textField.setTextFormatter(textFormatter); 

     textFormatter.valueProperty().addListener((ObservableValue<? extends Double> obs, Double oldValue, Double newValue) -> { 
      System.out.println("User entered value: "+newValue.doubleValue()); 
     }); 

     VBox root = new VBox(5, textField, new TextField()); 
     root.setAlignment(Pos.CENTER); 
     primaryStage.setScene(new Scene(root, 250, 250)); 
     primaryStage.show(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 

} 
1

Double.parseDouble Double Javadocを使用できます。これにより、独自の二重検証を記述するのではなく、解析が行われます。その後、数値書式例外またはNULLポインタ例外をチェックできます。

try 
    { 
     Double.parseDouble(newValue); 
     // Valid double 
    } 
    catch (NullPointerException | NumberFormatException ex) 
    { 
     // Not valid double 
    } 
+0

あなたの答えをありがとうが、私は**強** **ユーザーが2倍の値のみを入力しようとしています。無効な入力を管理しないようにしたいと思います。 – Robb1

+0

あなたが入力するように強制することができる唯一の方法は、とにかく無効な入力を検出することです。正規表現マッチでifを実行するか、上記のコードをtrueまたはfalseを返すtestDoubleメソッドにプルする間に違いはありません。 –

+1

"二重入力をユーザに強制することができる唯一の方法は、とにかく無効な入力を検出することです。"違います。たとえば、さまざまな 'insert'メソッドをオーバーライドしたり、' TextFormatter'を使用したりすることができます。 –

1

double型ではjava正規表現を使用し、数字以外の文字は数字で置き換えることができます。整数部分に許される桁数を指定する必要があります。たとえば、1,10です。

textField.textProperty().addListener(new ChangeListener<String>() { 
    @Override 
    public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) { 
     if (!newValue.matches("[0-9]{<range>}(\\.[0-9]*)?")) { 
      textField.setText(newValue.replaceAll("[^\\d.]", "")); 
      StringBuilder aus = new StringBuilder(newValue); 
      boolean firstPointFound = false; 
      for (int i = 0; i < aus.length(); i++){ 
       if(aus.charAt(i) == '.') { 
        if(!firstPointFound) 
         firstPointFound = true; 
        else 
         aus.deleteCharAt(i); 
       } 
      } 
      newValue = aus.toString(); 
     } 
    } 
}); 
+0

あなたの答えに感謝しますが、2番目の '.'で' 99.99.'を入力しようとするとエラーになります(さらに入力は '9999'に変更されます)。どのようにこれを修正するための任意のアイデア? – Robb1

+0

答えを変更しました。このコードを使用してみてください –

関連する問題