2016-12-26 22 views
1

初期化でChangeListenerの内部で変更メソッドを実行できますか。 変更が発生したときにのみ実行されるためです。例えば、私はそれが空のときに0に値です設定したいTextFieldを持っている、と私はこのようにそれを行う:JavaFX:ChangeListenerを実行

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]", "")); 
      } 

      if (newValue.isEmpty()) 
       textField.setText("0"); 

     } 
    }); 

しかし、アプリケーションの開始時に変更されたメソッドが呼び出されていません。だからこの問題を回避する方法は?

+0

アプリケーション起動時のテキストは何ですか? –

+0

それは空ですが、TextFieldは多くの場合の1つです。もう1つのケースは、TableViewで選択した項目に応じてプロパティを無効にするボタンです。 –

+0

しかし空の場合、リスナーはそれを '' 0 ''に変更します。だから、なぜそれを '' 0 ''に初期化しないのですか?他のコントロールと同様に、それらの状態があなたの必要条件と一致するようにそれらを初期化するだけです。 ( 'Button'を使うと、代わりに' button.disableProperty()。bind(tableView.getSelectionModel()。selectedItemProperty()。isNull()); ')を使うことができます。 –

答えて

2

プロパティに追加されたリスナーにアクセスする方法はありません。もちろん、あなたはそれへの参照を保持できます。

ChangeListener<String> textFieldListener = (observable, oldValue, newValue) -> { 

    if (!newValue.matches("\\d*")) { 
     textField.setText(newValue.replaceAll("[^\\d]", "")); 
    } 

    if (newValue.isEmpty()) 
     textField.setText("0"); 

}; 

textField.textProperty().addListener(textFieldListener); 
textFieldListener.changed(null, null, textField.getText()); 

または、おそらくより自然に、ちょうど別の方法を実際の機能を移動:

textField.textProperty().addListener((observable, oldValue, newValue) -> vetoTextFieldChanges()); 
vetoTextFieldChanges(); 

// ... 

private void vetoTextFieldChanges() { 
    String newText = textField.getText(); 
    if (!newText.matches("\\d*")) { 
     textField.setText(newText.replaceAll("[^\\d]", "")); 
    } 

    if (newText.isEmpty()) 
     textField.setText("0"); 
} 

注変化を見ての全体的なアプローチということと、それらがあなたのビジネスロジックと矛盾している場合にそれらを修正することは、あまり満足できるものではありません。たとえば、プロパティに登録されている他のリスナーがある場合、テキストの中間(無効な)値が表示されることがあります。これを行うためのサポートされている方法は、TextFormatterを使用することです。 TextFormatterは、の前にtextProperty()が更新される前に、テキストに要求された変更を拒否し、テキストを適切な値に変換することができます。だから、あなたが行うことができ、あなたのケースで:

UnaryOperator<TextFormatter.Change> filter = change -> { 

    // remove any non-digit characters from inserted text: 
    if (! change.getText().matches("\\d*")) { 
     change.setText(change.getText().replaceAll("[^\\d]", "")); 
    } 

    // if new text is empty, replace all text with "0": 
    if (change.getControlNewText().isEmpty()) { 
     change.setRange(0, change.getControlText().length()); 
     change.setText("0"); 
    } 

    return change ; 
}; 

TextFormatter<Integer> formatter = new TextFormatter<Integer>(new IntegerStringConverter(), 0, filter); 
textField.setTextFormatter(formatter); 

今、あなたはなど、フォーマッタのvalueプロパティ経由で直接(数値)の値を取得し、あなたのモデルにバインドするためにフォーマッタを使用することができます。

// assume model is a data model and valueProperty() returns a Property<Integer>: 
formatter.valueProperty().bindBidirectional(model.valueProperty()); 

このようなバインディングは、モデルが変更されたときにフォーマッタ(したがって結果としてテキストフィールド)を更新し、モデル値に応じて初期化します(したがって、元の質問に対する解決策を提供します)。

関連する問題