2017-06-07 29 views
1

我开发在JavaFX应用程序,在其中我动态创建TextFeids和复选框内GridPane这样的:JavaFx:如何在GridPane中更新动态创建的TextField的文本?

enter image description here

我加入该用户将在TextField中1和文本字段输入数字2在文本字段3显示像这样使用监听器:

enter image description here

问题:我要的是,当用户选中复选框,它应该增加10到值已经出现在的TextField 3中(与触发CheckBox相同的行)并更新TextField 3的文本,并且当用户取消选中CheckBox时,它应该从的TextField 3中存在的值中减去10触发复选框)和更新文本字段3.我试图做到这一点的文本,但它不工作(不添加和删除):

enter image description here

这是我如何创建GridPane:

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

     for(int i=0; i<rows; i++){ 
      TextField textField = new TextField(); 
      textField.setAlignment(Pos.CENTER); 
      TextField textField2 = new TextField(); 
      textField2.setAlignment(Pos.CENTER); 
      CheckBox checkBox = new CheckBox("Check Box"); 
      checkBox.setTextFill(Color.WHITE); 
      checkBox.setAlignment(Pos.CENTER); 
      TextField textField3 = new TextField(); 
      textField3.setAlignment(Pos.CENTER); 

      table.add(textField, 0, i); 
      table.add(textField2, 1, i); 
      table.add(checkBox , 2, i); 
      table.add(textField3,3, i); 

      GridPane.setMargin(textField, new Insets(5)); 
      GridPane.setMargin(textField2, new Insets(5)); 
      GridPane.setMargin(checkBox, new Insets(5)); 
      GridPane.setMargin(textField3, new Insets(5)); 
     } 
     table.setAlignment(Pos.CENTER); 

     return table; 
    } 

的方法,从表在特定行和列

public static Node getComponent (int row, int column, GridPane table) { 
    for (Node component : table.getChildren()) { 
     if(GridPane.getRowIndex(component) == row && 
         GridPane.getColumnIndex(component) == column) { 
      return component; 
     } 
    } 

    return null; 
} 

返回部件这是如何我加入:

public void add(GridPane table, int numRows){ 

     for(int i=0; i<numRows; i++){ 
      try { 

       int valueA = Integer.parseInt(((TextField)(getComponent (i, 0, table))).getText()); 
       System.out.println(valueA); 
       int valueB = Integer.parseInt(((TextField)(getComponent (i, 1, table))).getText()); 
       System.out.println(valueB); 

       int add = valueA+valueB; 

       String addToString = Integer.toString(add); 

       ((TextField)(getComponent (i, 3, table))).setText(addToString); 

       } catch (NullPointerException e) { 
        System.out.print("Caught the NullPointerException"); 
        } 
     } 

    } 

问题:加法和使用复选框减法:

 public void addPause(GridPane table, int numRows){ 

       for(int i=0; i<numRows; i++){ 

       boolean pause = ((CheckBox)(getComponent (i, 2, table))).isSelected(); 
       int getTextValue = Integer.parseInt(((TextField)(getComponent (i, 3, table))).getText()); 

       int addPause = getTextValue+10; 
       int removePause = addPause-10; 

       String addPToString = Integer.toString(addPause); 
       String removePToString = Integer.toString(removePause); 

       if (pause) { 
        ((TextField)(getComponent (i, 3, table))).setText(addPToString); 
       } else { 
        ((TextField)(getComponent (i, 3, table))).setText(removePToString); 
       } 
     } 
    } 

这是我如何触发使用听众:

 for(Node node : table.getChildren()){ 
      if(node instanceof TextField){ 
      ((TextField)node).textProperty().addListener((obs, old, newV)->{ 
       add(table, numRows); 
      }); 
     } 
      else if(node instanceof CheckBox){ 
       ((CheckBox)node).selectedProperty().addListener((obs, old, newV)->{ 
       addPause(table, numRows); 
      }); 
      } 
     } 
+2

你为什么不只是监听器添加到复选框,当你创建了吗?我给了你[上一个问题]一个完美可行的解决方案(https://stackoverflow.com/questions/44312354/javafx-how-to-compare-values-of-dynamically-created-textfields-inside-gridpane):完全相同的方法也可以在这里工作。 –

+0

@Jamed_D你的例子很好,但我需要重构整组代码。 – Junaid

+0

为什么你需要重构它,这与这个问题(或你的前一个问题)有什么关系? –

回答

1

正如我在您的previous question中所建议的那样,只需在创建控件的位置注册控件的侦听器即可。

实际上,对于两个文本字段和复选框,实际上可以只使用一个侦听器(在每行中),并在任何更改时更新第三个文本框。例如:

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

    for(int i=0; i<rows; i++){ 
     TextField textField = new TextField(); 
     textField.setAlignment(Pos.CENTER); 
     TextField textField2 = new TextField(); 
     textField2.setAlignment(Pos.CENTER); 
     CheckBox checkBox = new CheckBox("Check Box"); 
     checkBox.setTextFill(Color.WHITE); 
     checkBox.setAlignment(Pos.CENTER); 
     TextField textField3 = new TextField(); 
     textField3.setAlignment(Pos.CENTER); 

     table.add(textField, 0, i); 
     table.add(textField2, 1, i); 
     table.add(checkBox , 2, i); 
     table.add(textField3,3, i); 

     ChangeListener<Object> listener = (obs, oldValue, newValue) -> 
      updateTotalField(textField.getText(), textField2.getText(), checkBox.isSelected(), textField3); 

     textField.textProperty().addListener(listener); 
     textField2.textProperty().addListener(listener); 
     checkBox.selectedProperty().addListener(listener); 

     GridPane.setMargin(textField, new Insets(5)); 
     GridPane.setMargin(textField2, new Insets(5)); 
     GridPane.setMargin(checkBox, new Insets(5)); 
     GridPane.setMargin(textField3, new Insets(5)); 
    } 
    table.setAlignment(Pos.CENTER); 

    return table; 
} 

private static void updateTotalField(String text1, String text2, boolean addPause, TextField output) { 
    int value1 = parseText(text1); 
    int value2 = parseText(text2); 
    int total = value1 + value2 ; 
    if (addPause) { 
     total += 10 ; 
    } 
    output.setText(Integer.toString(total)); 
} 

private static int parseText(String text) { 
    // if text is a valid integer: 
    if (text.matches("\\d+")) { 
     return Integer.parseInt(text); 
    } else { 
     return 0 ; 
    } 
} 

现在你可以摆脱addaddPause方法和代码块你张贴在您遍历网格窗格的子节点,并添加监听器。除非您在其他地方需要,否则您可能无法使用getComponent()方法。

下面是代码为SSCCE

import javafx.application.Application; 
import javafx.beans.value.ChangeListener; 
import javafx.geometry.Insets; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.CheckBox; 
import javafx.scene.control.TextField; 
import javafx.scene.layout.GridPane; 
import javafx.scene.paint.Color; 
import javafx.stage.Stage; 

public class TableOfControlsInGridPane extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     Scene scene = new Scene(table(10)); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

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

     for(int i=0; i<rows; i++){ 
      TextField textField = new TextField(); 
      textField.setAlignment(Pos.CENTER); 
      TextField textField2 = new TextField(); 
      textField2.setAlignment(Pos.CENTER); 
      CheckBox checkBox = new CheckBox("Check Box"); 
      checkBox.setTextFill(Color.WHITE); 
      checkBox.setAlignment(Pos.CENTER); 
      TextField textField3 = new TextField(); 
      textField3.setAlignment(Pos.CENTER); 

      table.add(textField, 0, i); 
      table.add(textField2, 1, i); 
      table.add(checkBox , 2, i); 
      table.add(textField3,3, i); 

      ChangeListener<Object> listener = (obs, oldValue, newValue) -> 
       updateTotalField(textField.getText(), textField2.getText(), checkBox.isSelected(), textField3); 

      textField.textProperty().addListener(listener); 
      textField2.textProperty().addListener(listener); 
      checkBox.selectedProperty().addListener(listener); 

      GridPane.setMargin(textField, new Insets(5)); 
      GridPane.setMargin(textField2, new Insets(5)); 
      GridPane.setMargin(checkBox, new Insets(5)); 
      GridPane.setMargin(textField3, new Insets(5)); 
     } 
     table.setAlignment(Pos.CENTER); 

     return table; 
    } 

    private void updateTotalField(String text1, String text2, boolean addPause, TextField output) { 
     int value1 = parseText(text1); 
     int value2 = parseText(text2); 
     int total = value1 + value2 ; 
     if (addPause) { 
      total += 10 ; 
     } 
     output.setText(Integer.toString(total)); 
    } 

    private int parseText(String text) { 
     // if text is a valid integer: 
     if (text.matches("\\d+")) { 
      return Integer.parseInt(text); 
     } else { 
      return 0 ; 
     } 
    } 

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

和截图: enter image description here

由于Java是一种面向对象的语言,它很可能似乎更适合做这一种对象 - 首先是面向导向的方式。我不知道什么样的数据,你在这个观点代表,但你应该定义封装在一个行的数据一类:

import javafx.beans.binding.Bindings; 
import javafx.beans.property.BooleanProperty; 
import javafx.beans.property.IntegerProperty; 
import javafx.beans.property.ReadOnlyIntegerProperty; 
import javafx.beans.property.ReadOnlyIntegerWrapper; 
import javafx.beans.property.SimpleBooleanProperty; 
import javafx.beans.property.SimpleIntegerProperty; 

// Obviously use a more sensible name for the class: 
public class RowData { 

    private final IntegerProperty firstValue = new SimpleIntegerProperty(); 
    private final IntegerProperty secondValue = new SimpleIntegerProperty(); 
    private final BooleanProperty includePause = new SimpleBooleanProperty(); 
    private final ReadOnlyIntegerWrapper total = new ReadOnlyIntegerWrapper(); 

    public RowData() { 
     total.bind(Bindings.createIntegerBinding(() -> { 
      int total = getFirstValue() + getSecondValue() ; 
      if (isIncludePause()) { 
       total += 10 ; 
      } 
      return total ; 
     }, firstValue, secondValue, includePause)); 
    } 

    public final IntegerProperty firstValueProperty() { 
     return this.firstValue; 
    } 


    public final int getFirstValue() { 
     return this.firstValueProperty().get(); 
    } 


    public final void setFirstValue(final int firstValue) { 
     this.firstValueProperty().set(firstValue); 
    } 


    public final IntegerProperty secondValueProperty() { 
     return this.secondValue; 
    } 


    public final int getSecondValue() { 
     return this.secondValueProperty().get(); 
    } 


    public final void setSecondValue(final int secondValue) { 
     this.secondValueProperty().set(secondValue); 
    } 


    public final BooleanProperty includePauseProperty() { 
     return this.includePause; 
    } 


    public final boolean isIncludePause() { 
     return this.includePauseProperty().get(); 
    } 


    public final void setIncludePause(final boolean includePause) { 
     this.includePauseProperty().set(includePause); 
    } 


    public final ReadOnlyIntegerProperty totalProperty() { 
     return this.total.getReadOnlyProperty(); 
    } 


    public final int getTotal() { 
     return this.totalProperty().get(); 
    } 

} 

然后一个类来显示这些数据:

import javafx.beans.binding.Bindings; 
import javafx.beans.property.IntegerProperty; 
import javafx.beans.property.StringProperty; 
import javafx.scene.control.CheckBox; 
import javafx.scene.control.TextField; 
import javafx.scene.layout.GridPane; 

public class RowDataView { 

    private final TextField firstValueField ; 
    private final TextField secondValueField ; 
    private final CheckBox includePauseBox ; 
    private final TextField totalField ; 

    public RowDataView(RowData data) { 

     firstValueField = new TextField(); 
     bindToStringProperty(data.firstValueProperty(), firstValueField.textProperty()); 

     secondValueField = new TextField(); 
     bindToStringProperty(data.secondValueProperty(), secondValueField.textProperty()); 

     includePauseBox = new CheckBox(); 
     data.includePauseProperty().bind(includePauseBox.selectedProperty()); 

     totalField = new TextField(); 
     totalField.setEditable(false); 
     totalField.textProperty().bind(data.totalProperty().asString()); 
    } 

    public void addToGridPane(GridPane pane, int row, int firstValueColumn, int secondValueColumn, int checkboxColumn, int totalColumn) { 
     pane.add(firstValueField, firstValueColumn, row); 
     pane.add(secondValueField, secondValueColumn, row); 
     pane.add(includePauseBox, checkboxColumn, row); 
     pane.add(totalField, totalColumn, row); 
    } 

    public void addToGridPane(GridPane pane, int row, int column) { 
     addToGridPane(pane, row, column, column+1, column+2, column+3); 
    } 

    public void addToGridPane(GridPane pane, int row) { 
     addToGridPane(pane, row, 0); 
    } 

    private void bindToStringProperty(IntegerProperty p, StringProperty s) { 
     p.bind(Bindings.createIntegerBinding(
       () -> { 
        if (s.get().matches("\\d+")) { 
         return Integer.parseInt(s.get()); 
        } 
        return 0 ; 
       }, s)); 
    } 
} 

这里是一些测试代码:

import java.util.ArrayList; 
import java.util.List; 

import javafx.application.Application; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.layout.GridPane; 
import javafx.stage.Stage; 

public class TableOfControlsInGridPane extends Application { 

    private final List<RowData> data = new ArrayList<>(); 

    @Override 
    public void start(Stage primaryStage) { 
     Scene scene = new Scene(table(10), 800, 800); 
     scene.getStylesheets().add("style.css"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    public GridPane table(int rows){ 
     GridPane table = new GridPane(); 
     table.getStyleClass().add("data-grid"); 

     data.clear(); 

     for(int i=0; i<rows; i++){ 

      RowData rowData = new RowData(); 
      data.add(rowData); 

      RowDataView rowDataView = new RowDataView(rowData); 
      rowDataView.addToGridPane(table, i); 
     } 
     table.setAlignment(Pos.CENTER); 
     return table; 
    } 

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

我感动的样式样式表(style.css):

为实现这一
.data-grid { 
    -fx-background-color: purple ; 
    -fx-hgap: 10 ; 
    -fx-vgap: 10 ; 
} 
.data-grid .text-field, .data-grid .check-box { 
    -fx-alignment: center ; 
} 
.data-grid .check-box { 
    -fx-text-fill: white ; 
} 
+0

谢谢@James_D的详细解答,我会尽量以OOP方式实现它。 – Junaid

1

一种方式是通过在Table(GridPane)添加ChangeListenerCheckBox,这样的事情:

/** 
* This method to change the current value of the TextField at 
* column 3 in the Table(GridPane) by ten 
* @param table 
*/ 
private static void changeByTen(GridPane table){ 
    // loop through every node in the GridPane 
    for(Node node : table.getChildren()){ 
     // and for every CheckBox 
     if(node instanceof CheckBox){ 
      // add change listener to the Selected Property 
      ((CheckBox)node).selectedProperty().addListener((obs, unSelected, selected)->{ 
       // get the TextField at third column that corresponds to this CehckBox 
       TextField targetTextFeild = 
         ((TextField)getComponent(GridPane.getRowIndex(node), 3, table)); 
       try{// then try to add/subtract 
        if(selected){// if checked add 10 
        targetTextFeild.setText(String.valueOf(
         Integer.parseInt(targetTextFeild.getText())+10)); 
        } 
        else if(!selected){ // if unchecked subtract 10 
          targetTextFeild.setText(String.valueOf(
          Integer.parseInt(targetTextFeild.getText())-10)); 
        } 
       }catch(Exception e){// do nothing} 
      }); 
     } 
    } 
} 

然后在tabPane ChangeListener添加这个方法:

tabPane.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>(){ 
    ...... 
    ...... 
    // I think you have here anchorPane not containerB in the original code 
    changeByTen((GridPane) containerB.getChildren().get(0)); 
} 

测试

Test

+0

@Junaid如果您有任何关于答案的问题,请告诉我。 – Yahya

+0

谢谢你的回答@Yahya :) – Junaid

+0

你绝对是我的朋友@Yahya。谢谢你总是指导我:) – Junaid

相关问题