2013-12-14 3 views
6

テキストが変更されたときに、いくつかのTextFieldで検証を実行する必要があります。検証はまったく同じなので、私は1つの手順を使用すると考えました。コントロールにフォーカスがない場合でも検証を実行する必要があるため、onInputMethodTextChangedを使用することはできません。そこで、ChangeListenertextPropertyに追加しました。JavaFX変更リスナー内で呼び出し側ノードを決定する

private TextField firstTextField; 
private TextField secondTextField; 
private TextField thirdTextField; 

protected void initialize() { 
    ChangeListener<String> textListener = new ChangeListener<String>() { 
     @Override 
     public void changed(ObservableValue<? extends String> observable, 
       String oldValue, String newValue) { 
      // Do validation 
     } 
    }; 

    this.firstTextField.textProperty().addListener(textListener); 
    this.secondTextField.textProperty().addListener(textListener); 
    this.thirdTextField.textProperty().addListener(textListener); 
} 

しかし、検証を実行中に、どのTextFieldが変更をトリガしたかを知る方法がありません。どのようにしてこの情報を入手できますか?

答えて

10

は2つの方法があります。あなただけTextFieldのtextプロパティで、このリスナーを登録すると仮定すると、

changed(...)メソッドに渡されるObservableValueはそのtextPropertyへの参照です。それはTextFieldを返すgetBean()メソッドを持っています。ですから、

StringProperty textProperty = (StringProperty) observable ; 
TextField textField = (TextField) textProperty.getBean(); 

を行うことができますが、TextFieldtextProperty以外のものを使用してリスナーを登録する場合、これは明らかに(ClassCastExceptionで)中断しますが、それはあなたが同じリスナーのインスタンスを再利用することができます。

より堅牢な方法ではなく、匿名クラスの内部クラスとしてリスナークラスを作成し、TextFieldへの参照を保持することがあります

private class TextFieldListener implements ChangeListener<String> { 
    private final TextField textField ; 
    TextFieldListener(TextField textField) { 
    this.textField = textField ; 
    } 
    @Override 
    public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) { 
    // do validation on textField 
    } 
} 

、その後

this.firstTextField.textProperty().addListener(new TextFieldListener(this.firstTextField)); 

など

+0

'ClassCastException'を避けるには、' TextField'ではなく 'Control'を期待し、' Control'が 'TextField'なのかどうかを確認してください。if(mControl instanceof TextField)(TextField)mControl ).doSomething() ' –

0
@Override 
public void changed(ObservableValue observableValue, Object o, Object n) { 
    try { 
     StringProperty textProperty = (StringProperty) observableValue ; 
     TextField textField = (TextField) textProperty.getBean(); 

     if (textField == textFieldChannel1) { 

     } else if (textField == textFieldChannel2) { 

     } else if (textField == textFieldChannel3) { 

     } 
    } catch (Exception e) { 
     //e.printStackTrace(); 
    } 
} 
0

私は同様の問題がありましたが、giから解決策を導くことができませんでしたベンの答え。だから、私は、次の人の理解を深めるのに役立つサンプルプログラムを作ろうと考えました。すべてのテキストフィールドに数値が入力されるまで、ボタンは有効になりません。

メイン:

/** 
* 
* @author blj0011 
*/ 
public class DoubleFieldValidator extends Application { 

    @Override 
    public void start(Stage stage) throws Exception { 
     Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml")); 

     Scene scene = new Scene(root); 

     stage.setScene(scene); 
     stage.show(); 
    } 

    /** 
    * @param args the command line arguments 
    */ 
    public static void main(String[] args) { 
     launch(args); 
    }  
} 

コントローラー:

import java.net.URL; 
import java.util.ArrayList; 
import java.util.Random; 
import java.util.ResourceBundle; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.event.ActionEvent; 
import javafx.fxml.FXML; 
import javafx.fxml.Initializable; 
import javafx.scene.control.Button; 
import javafx.scene.control.TextField; 
import javafx.scene.layout.AnchorPane; 
import javafx.scene.layout.VBox; 

/** 
* 
* @author blj0011 
*/ 
public class FXMLDocumentController implements Initializable {  
    @FXML private Button btnMain; 
    @FXML private AnchorPane apScrollPane; 

    ObservableList<TextField> textFieldContainer = FXCollections.observableArrayList(); 
    ArrayList<Boolean> fieldValidatorContainer = new ArrayList(); 

    @FXML 
    private void handleButtonAction(ActionEvent event) { 
     System.out.println("You pressed me!"); 
    } 

    @Override 
    public void initialize(URL url, ResourceBundle rb) { 
     // TODO 
     btnMain.setDisable(true);//Disable button until all fields are validated 
     Random random = new Random(); 
     //create textfields on the fly 
     for(int i = 0; i < random.nextInt(20) + 1; i++)//creates 1 to 20 textfields 
     { 
      textFieldContainer.add(new TextField());//create textfield and add it to container 
      fieldValidatorContainer.add(false);//set corresponding validator container to false;   
     } 
     VBox vbox = new VBox(); 
     vbox.getChildren().addAll(textFieldContainer); 
     apScrollPane.getChildren().add(vbox); 

     //create a listener for each textfield 
     for(int i = 0; i < textFieldContainer.size(); i++) 
     { 
      textFieldContainer.get(i).textProperty().addListener((observable, oldValue, newValue) -> { 
       System.out.println("observable: " + observable); 
       //loop though the textfieldContainer to find right container 
       for(int t = 0; t < textFieldContainer.size(); t++) 
       { 
        //look for right container. once found get container's index t 
        if(textFieldContainer.get(t).textProperty().equals((observable))) 
        { 
         System.out.println("object t: " + t); 
         fieldValidatorContainer.set(t, fieldValidator(newValue)) ;//set validator container at corresponding index 
         fieldValidatorCheck(); //run the check to see if the button should be enabled or not. 
        } 
       } 
      }); 
     } 
    } 

    //used to check if field has double value or not. 
    private boolean fieldValidator(String data){   
     try 
     { 
      double d = Double.parseDouble(data); 
      return true; 
     } 
     catch(NumberFormatException ex) 
     { 
      return false; 
     }   
    } 

    //used to disable or enable update button 
    private void fieldValidatorCheck() 
    {   
     for(int i = 0; i < fieldValidatorContainer.size(); i++) 
     { 
      System.out.println("poition " + i + ": " + fieldValidatorContainer.get(i)); 
      if(fieldValidatorContainer.get(i) == false) 
      { 
       btnMain.setDisable(true); 
       return; 
      } 
     } 

     btnMain.setDisable(false); 
    } 
} 

FXML:

<?xml version="1.0" encoding="UTF-8"?> 

<?import javafx.scene.control.Button?> 
<?import javafx.scene.control.ScrollPane?> 
<?import javafx.scene.layout.AnchorPane?> 

<AnchorPane id="AnchorPane" prefHeight="330.0" prefWidth="459.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="doublefieldvalidator.FXMLDocumentController"> 
    <children> 
     <Button fx:id="btnMain" layoutX="284.0" layoutY="144.0" onAction="#handleButtonAction" text="Click Me!" /> 
     <ScrollPane fx:id="spMain" layoutX="30.0" layoutY="30.0" prefHeight="297.0" prefWidth="200.0"> 
     <content> 
      <AnchorPane fx:id="apScrollPane" minHeight="0.0" minWidth="0.0" prefHeight="279.0" prefWidth="200.0" /> 
     </content> 
     </ScrollPane> 
    </children> 
</AnchorPane> 
関連する問題