I'm developing an application using JavaFx in which I'm creating dynamic TextFields inside a GridPane and there is a Button which is initially disabled like this:
So what I want is if Column 1 TextFields values are less than Column 3 TextFields values, button should be enable like this:
But let say if any of Column 3 TextField value become less than Column 1 TextField value of same row, it should disable button and show that specific TextField border in red color and when hover mouse over that field should display some warning:
I'm creating TextField like this:
public static GridPane table(int rows){
GridPane table = new GridPane();
for(int i=0; i<rows; i++){
TextField textField1 = new JFXTextField();
textField1.setAlignment(Pos.CENTER);
TextField textField2 = new JFXTextField();
textField2.setAlignment(Pos.CENTER);
TextField textField3 = new JFXTextField();
textField3.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);
}
return table;
}
After that I'm creating another method to return component from table at specific row and column like this:
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;
}
I tried to do like this but it's not working (Here I'm converting values into string and comparing just for the check):
private boolean isTextEqual(GridPane table, Button button){
for(Node node : table.getChildren()){
if(node instanceof TextField){
for(int i=1 ; i<=ComboBox().getValue(); i++){
String str = ((TextField)DynamicGridpanes.getComponent (i, 0, table)).getText();
((TextField)DynamicGridpanes.getComponent (i, 2, table)).textProperty().addListener((obs, old, newV)->{
if(newV.toString()==str){
button.setDisable(false);
}
else{
button.setDisable(true);
}
});
}
}
}
return true;
}
You can create the bindings that do the validation when you create the text fields. This will avoid the need to navigate through the grid pane's child nodes, which doesn't seem very robust.
Declare an array of boolean bindings (there will be one for each row):
Then you can do
You can also add the styling to the text field directly in the
for
loop:and for tooltips:
Actually it's not that easy to do what you want, because the code you have needs to be refactored (the code is not meant to do such advanced requirements but it's fine for the basic requirements you have). However, you can do something like this:
First, define a global variable to be updated with the
last row index
of the invalidTextField
(From here you shall conclude that this will change the border color for ONE invalidTextField
at a time):Now with the help of the method you already have
getComponent (int row, int column, GridPane table)
, create another static method to check if ALLTextFields
have Valid Values at one time:Now you need to use the above method in the
validateTable()
method and do some adjustments:Now in your
tabPane ChangeListener
add the third para to the method (because you already have it you need just to add the value ofComboBox
:Test