【问题标题】:JavaFx: How to validate mutilple TextFields creating at run time?JavaFx:如何在运行时验证多个文本字段的创建?
【发布时间】:2017-05-31 01:22:10
【问题描述】:

我在运行时使用 for 循环创建多个 TextField,并将它们添加到 Gridpane(有 8 列)内部,如下所示:

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;
    }

接下来我将创建另一种方法来从特定行和列的表中返回组件,如下所示:

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;
     }

问题在这里:我想验证每个 TextField,所以如果用户忘记在任何 TextField 中写入,我想禁用 Button,为此我使用绑定像这样:

 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()))
                    );
                }
     }

但是发生的事情是它只验证最后一行,假设我在 Gridpane 中创建了 3 行 textfeilds,所以它只验证第 3 行而不是第 1 行和第 2 行,并且基于第 3 行条目,它启用了按钮但是我想要在验证所有应该启用按钮的行之后,否则不会。请帮助我如何实现这一目标。

【问题讨论】:

  • 什么是JFXTextField?为什么不使用TextField
  • @Yahya Learn google-fu 这将很快提出一个事实,即它是来自JFoenix 的控件,并且使用它基本上是一种设计选择。虽然在这种情况下,它只会使描述变得比必要的复杂......

标签: java javafx javafx-2 javafx-8


【解决方案1】:

您的绑定逻辑是正确的。但是,由于for loop [for(int i=1 ; i&lt;=comboBox().getValue(); i++)] 的问题会破坏您的工作。所有TextFields 都位于列索引 0,唯一改变的是行索引。因此,您应该在 for loop 中对所有 TextFields 使用 getComponent(i, 0, table);,而无需将 列索引 更改为 12 .. 等等。但这也不能解决问题,因为在每个循环中,您都将 ALL TextFields 分配给相同的 index 然后覆盖它在每个循环中,直到它们都指向索引comboBox().getValue() 和列0 处的TextField(这就是为什么它适用于您提到的最后一行)。

我会建议不同的方法,如下所示:

首先您需要一种方法来检查所有其他TextFields 是否已填充/不为空:

/**
* 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;
 }

其次,收听表格中每个TextField 的文本更改,并在每次更改时检查所有其他TextField 是否已填充/不为空:

/**
* 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 
          }
      });
   }    
}

此外,您需要将按钮设置为在创建后禁用一次。

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

最后需要在tabPaneChange Listener Block中添加方法:

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

测试

【讨论】:

  • 它解决了我的问题,感谢您的解释,谢谢@Yahya :)
  • 另一件事@Yahya 如果在 Tab B 我有另一个表,让说 TableA 在另一个带有 TextField CheckBox 的容器中,并且按钮也依赖于这个 TableA 的验证,所以这样做我必须为它制定单独的方法,或者我可以使用相同的方法:private void validateTable(GridPane table, GridPane tableA, Button button)
  • @Junaid 如果TableAGridPane 并且包含TextFields,那么您绝对可以对该表使用相同的方法。
  • 好的@Yahya但TableA不在同一个GridPane中,它在不同的GridPane中。所以我试着像你说的那样做,但问题是当 Table 的所有条目都被验证时,它会立即启用按钮 (Problem) 而不检查不同 gridPane 中的 TableA 条目。因此,当我单击 TableA 字段后,它将再次禁用该按钮,直到 TableA 条目验证。但我希望程序应该同时验证 Table 和 TableA (两者都在不同的 GridPanes) 然后不一个一个地启用按钮。如果你不明白我想说什么,我会更新我的问题。
  • link@Yahya 你现在可以检查一下吗。
猜你喜欢
  • 1970-01-01
  • 2016-12-07
  • 2022-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多