2017-05-30 3 views
1

Je crée plusieurs TextFields au moment de l'exécution à l'aide de boucles et de les ajouter à l'intérieur Gridpane (qui a 8 colonnes) comme ceci:JavaFx: Comment valider plusieurs TextFields lors de l'exécution?

public static GridPane table(int rows){ 
      GridPane table = new GridPane(); 

      for(int i=0; i<rows; i++){ 
      JFXTextField textField1 = new JFXTextField(); 
      textField1.setAlignment(Pos.CENTER); 
      JFXTextField textField2 = new JFXTextField(); 
      textField1.setAlignment(Pos.CENTER); 
      JFXTextField textField3 = new JFXTextField(); 
      textField1.setAlignment(Pos.CENTER); 
      JFXTextField textField4 = new JFXTextField(); 
      textField1.setAlignment(Pos.CENTER); 
      JFXTextField textField5 = new JFXTextField(); 
      textField1.setAlignment(Pos.CENTER); 
      JFXTextField textField6 = new JFXTextField(); 
      textField1.setAlignment(Pos.CENTER); 
      JFXTextField textField7 = new JFXTextField(); 
      textField1.setAlignment(Pos.CENTER); 
      JFXTextField textField8 = new JFXTextField(); 
      textField1.setAlignment(Pos.CENTER); 

      //add them to the GridPane 
      table.add(textField1, 0, i+1); 
      table.add(textField2, 1, i+1); 
      table.add(textField3, 2, i+1); 
      table.add(textField4, 3, i+1); 
      table.add(textField5, 4, i+1); 
      table.add(textField6, 5, i+1); 
      table.add(textField7, 6, i+1); 
      table.add(textField8, 7, i+1); 
     } 
     return table; 
    } 

Ensuite je crée une autre méthode pour revenir composant de table à particulier ligne et colonne comme ceci:

public static Node getComponent (int row, int column, GridPane table) { 
     for (Node component : table.getChildren()) { // loop through every node in the table 
      if(GridPane.getRowIndex(component) == row && 
          GridPane.getColumnIndex(component) == column) { 
       return component; 
      } 
     } 

     return null; 
    } 

le problème est ici: Je veux valider chacun des TextField, donc si l'utilisateur oublie d'écrire dans l'un des TextField, je veux désactiver le bouton, à cet effet J'utilise la liaison comme ceci:

private void validatingGrid() { 
     GridPane table = (GridPane) anchorPane().getChildren().get(0); 

     for(int i=1 ; i<=comboBox().getValue(); i++){ 
      JFXTextField text0 = ((JFXTextField)getComponent (i, 0, table)); 
      JFXTextField text1 = ((JFXTextField)getComponent (i, 1, table)); 
      JFXTextField text2 = ((JFXTextField)getComponent (i, 2, table)); 
      JFXTextField text3 = ((JFXTextField)getComponent (i, 3, table)); 
      JFXTextField text4 = ((JFXTextField)getComponent (i, 4, table)); 
      JFXTextField text5 = ((JFXTextField)getComponent (i, 5, table)); 
      JFXTextField text6 = ((JFXTextField)getComponent (i, 6, table)); 
      JFXTextField text7 = ((JFXTextField)getComponent (i, 7, table)); 

       button.disableProperty().bind(
         Bindings.isEmpty(text0.textProperty()) 
         .or(Bindings.isEmpty(text1.textProperty())) 
         .or(Bindings.isEmpty(text2.textProperty())) 
         .or(Bindings.isEmpty(text3.textProperty())) 
         .or(Bindings.isEmpty(text4.textProperty())) 
         .or(Bindings.isEmpty(text5.textProperty())) 
         .or(Bindings.isEmpty(text6.textProperty())) 
         .or(Bindings.isEmpty(text7.textProperty())) 
        ); 
       } 
    } 

Mais ce qui se passe est-il est seulement la validation de la dernière ligne, nous allons dire si je crée 3 rangées de textfeilds dans le Gridpane, il est donc seulement la validation de 3ème rangée non 1er et 2e rangs et sur la base des entrées de la 3e rangée, il est activer le bouton, mais je veux après avoir validé toutes les lignes, il devrait activer le bouton sinon. S'il vous plaît aidez-moi comment puis-je y parvenir.

+0

Qu'est-ce que 'JFXTextField'? Pourquoi ne pas utiliser 'TextField' – Yahya

+0

@Yahya Apprenez google-fu cela rapidement fait ressortir le fait que c'est un contrôle de [JFoenix] (https://github.com/jfoenixadmin/JFoenix) et l'utiliser est fondamentalement un choix de conception. Bien que dans ce cas, il rend juste la description plus compliquée que nécessaire ... – fabian

Répondre

2

Votre logique de liaison est correcte. Cependant, le problème à cause du for loop [for(int i=1 ; i<=comboBox().getValue(); i++)], qui ruine votre travail. Tous TextFields sont à index de la colonne0 et la seule chose qui change est l'indice de ligne. Donc, vous devez utiliser getComponent(i, 0, table); pour tous TextFields dans votre for loop sans changer l'colonne index à 1, 2 .. et ainsi de suite. Mais cela aussi ne résoudra pas le problème parce que dans chaque boucle que vous affectez ALLTextFields au même indice et écrasera dans chaque boucle jusqu'à ce que tous les points de l'TextField à l'index comboBox().getValue() et la colonne 0 (C'est pourquoi ça marche pour la dernière rangée comme tu l'as mentionné).

Je suggère approche différente, quelque chose comme ceci:

Vous devez d'abord une méthode pour vérifier si tous les autres TextFields sont remplis/pas vide:

/** 
* Check if all the TextFields are filled and not empty 
* @param table 
*/ 
private static boolean isAllFilled(GridPane table){ 
    for(Node node : table.getChildren()){ // cycle through every component in the table (GridPane) 
     if(node instanceof TextField){ // if it's a TextField 
     // after removing the leading spaces, check if it's empty 
      if(((TextField)node).getText().trim().isEmpty()){ 
        return false; // if so, return false 
      } 
     }  
    } 
    return true; 
} 

En second lieu, Écouter la Changements de texte pour chaque TextField dans le tableau, et à chaque changement, vérifiez si tous les autres TextField sont remplis/non vides:

/** 
* To Validate the Table (GridPane) 
* This method should be added to the tabPane change listener 
* @param table 
* @param button 
*/ 
private void validateTable(GridPane table, Button button) { 

    for(Node node : table.getChildren()){ // cycle through every component in the table (GridPane) 
     if(node instanceof TextField){ // if it's a TextField 
     ((TextField)node).textProperty().addListener((obs, old, newV)->{ // add a change listener to every TextField 
     // then check if the new value is not empty AND all other TextFields are not empty 
      if(!newV.trim().isEmpty()&&isAllFilled(table)){ 
      button.setDisable(false); // then make the button active again 
      } 
      else{ 
       button.setDisable(true); // or else, make it disable until it achieves the required condition 
      } 
     }); 
    }  
} 

De même, vous devez définir le bouton pour le désactiver une fois après sa création.

Button button = new Button("Test"); 
button.setDisable(true); 

Enfin, vous devez ajouter la méthode dans le changement tabPane Listener Bloc:

tabPane.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>(){ 
     ......... 
     ......... 
     ......... 
     validateTable((GridPane) anchorPane().getChildren().get(0), test); 
} 

test

Testing

+0

il a résolu mon problème et merci pour l'explication, Merci @Yahya :) – Junaid

+0

Une autre chose @Yahya si dans ** Tab B ** J'ai un autre La table indique que TableA dans un autre conteneur avec TextField CheckBox et le bouton dépend également de la validation de cette TableA donc je dois faire des méthodes séparées ou je peux utiliser la même méthode comme ceci: 'private void validateTable (GridPane table, GridPane tableA, bouton Button) ' – Junaid

+0

@Junaid Si' TableA' est un 'GridPane' et contient 'TextFields', vous pouvez absolument utiliser la même méthode pour cette table. – Yahya