Reputation: 55
I have 14 pairs of Buttons associated with two groups of textFields that increment and decrement their associated textFields by 2. Each text field displays how many pairs of plates of specific weights are to be loaded onto a barbell. They are stored in two 2-dimensional arrays, one for pounds and the other for kilograms. [increment or decrement][buttons]
final Button[][] poundIncrementDecrementButton = new Button[2][7];
final Button[][] kilogramIncrementDecrementButton = new Button[2][7];
I'm using Scene Builder and JavaFX, and I'm trying to avoid writing 28 @FXML event handlers. This is the method I've come up with so far to iterate through each of the arrays, but I'm not sure how I can replace the lambda expressions to make this work.
// assigns event handlers to increment and decrement buttons.
private void incrementDrecimentButtonEventHandlers() {
// p=1 increment buttons, p=2 decrement buttons
for (int p = 0; p < poundIncrementDecrementButton.length; p++) {
// loops through buttons
for (int j = 0; j < poundIncrementDecrementButton[p].length; j++) {
Button incrementButton = poundIncrementDecrementButton[p][j];
final int incrementDecriment = p;
final int textField = j;
incrementButton.setOnAction((ActionEvent event) -> {
incrementDecrementPlate("pounds", incrementDecriment, textField);
});
}
// k=1 increment buttons, k=2 decrement buttons
for (int k = 0; k < kilogramIncrementDecrementButton.length; k++) {
// loops through buttons
for (int j = 0; j < kilogramIncrementDecrementButton[k].length; j++) {
Button incrementButton = kilogramIncrementDecrementButton[k][j];
final int incrementDecriment = k;
final int textField = j;
incrementButton.setOnAction((ActionEvent event) -> {
incrementDecrementPlate("kilograms", incrementDecriment, textField);
});
}
}
}
}
I then have the event handlers call this method with the relevant indices.
// increments or decrements the plates
private void incrementDecrementPlate(String unit, int incrementDecrement, int textField) {
Double oldValue = Double.parseDouble(poundTextFieldList.get(textField).getText());
String incremented;
String decremented;
if (oldValue % 2 != 0) {
incremented = Double.toString(oldValue + 1);
} else {
incremented = Double.toString(oldValue + 2);
}
if (oldValue % 2 != 0) {
decremented = Double.toString(oldValue - 1);
} else if (oldValue != 0) {
decremented = Double.toString(oldValue - 2);
} else {
decremented = Double.toString(oldValue);
}
switch (unit) {
case "pounds":
if (incrementDecrement == 0) {
poundTextFieldList.get(textField).setText(incremented);
} else {
poundTextFieldList.get(textField).setText(decremented);
}
break;
case "kilograms":
if (incrementDecrement == 0) {
kilogramTextFieldList.get(textField).setText(incremented);
} else {
kilogramTextFieldList.get(textField).setText(decremented);
}
break;
}
}
Upvotes: 1
Views: 3032
Reputation: 55
After some experimentation, I came up with a solution. Keep in mind, this is my attempt at sticking to MVC architecture using Scene Builder, FXML, and JavaFX.
There are 14 different plates, 7 in lbs and 7 in kgs. Each plate has a text field to display how many of each are needed to be loaded on a barbell for a given weight. These textFields are stored in ObservableLists and are given listeners elsewhere in the controller.
// textFields associated with 45, 35, 25, 15, 10, 5, 2.5lb plates
ObservableList<TextField> poundTextFieldList = FXCollections.observableArrayList();
// textFields associated with 25, 20, 15, 10, 5, 2.5, 1.25kg plates
ObservableList<TextField> kilogramTextFieldList = FXCollections.observableArrayList();
These arrays store the number of plates.
int[] poundPlatesToLoad = calculator.getPoundPlatesToLoad();
int[] kilogramPlatesToLoad = calculator.getKilogramPlatesToLoad();
These ArrayLists store the increment buttons
private final ArrayList<Button> poundIncrementButtons = new ArrayList();
private final ArrayList<Button> poundDecrementButtons = new ArrayList();
private final ArrayList<Button> kilogramIncrementButtons = new ArrayList();
private final ArrayList<Button> kilogramDecrementButtons = new ArrayList();
Since I used Scene Builder to design the GUI, each button requires @FXML tags to identify them. I don't think there is a way around this, so there are 28 of these in the controller.
@FXML
private Button poundIncrement45Button;
@FXML
private Button poundDecrement45Button;
Then, to avoid writing 28 handlers, I wrote 4 handlers associated with each ArrayList.
public void poundIncrementButtonPressed(ActionEvent event) {
System.out.println("pound increment button pressed");
Button button = (Button) event.getSource();
// identifies which plate is to be incremented
int plate = poundIncrementButtons.indexOf(button);
incrementDecrementPlate(0, 0, plate);
}
And one more method to increment or decrement the correct textField.
private void incrementDecrementPlate(int unit, int incrementDecrement, int textField) {
int oldValue;
if(unit == 0){
oldValue = (int) poundPlatesToLoad[textField];
} else {
oldValue = (int) kilogramPlatesToLoad[textField];
}
String incremented;
String decremented;
if (oldValue % 2 != 0) {
incremented = Integer.toString(oldValue + 1);
} else {
incremented = Integer.toString(oldValue + 2);
}
if (oldValue % 2 != 0) {
decremented = Integer.toString(oldValue - 1);
} else if (oldValue != 0) {
decremented = Integer.toString(oldValue - 2);
} else {
decremented = Integer.toString(oldValue);
}
switch (unit) {
case 0:
if (incrementDecrement == 0) {
poundTextFieldList.get(textField).setText(incremented);
} else {
poundTextFieldList.get(textField).setText(decremented);
}
break;
case 1:
if (incrementDecrement == 0) {
kilogramTextFieldList.get(textField).setText(incremented);
} else {
kilogramTextFieldList.get(textField).setText(decremented);
}
break;
}
}
Here's an image of the program so far. Each text field dynamically responds to changes. The barbell on the right displays kilogram plates in response to changes in the textFields.
Upvotes: 1
Reputation: 18812
The following code demonstrates how to have group of (2) buttons incrementing the value of a text field:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
public class FxMain extends Application {
private Button[] increment, decrement;
private TextField[] txt;
private static final int numberOfGroups = 3;
@Override
public void start(Stage stage) {
initComponents(numberOfGroups);
GridPane root = new GridPane();
for(int row =0; row < numberOfGroups; row++){ //add all components
root.addRow(row, decrement[row], txt[row],increment[row]);
}
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
//create and initialize components
private void initComponents(int size) {
increment = new Button[size]; decrement = new Button[size];
txt = new TextField[size];
for(int group = 0; group < size; group++) {
final int i = group;
txt[i] = new TextField(String.valueOf(0));
increment[i] = new Button("+");
increment[i].setOnAction(a-> updateTxtField(txt[i], 1));//assign handle
decrement[i] = new Button("-");
decrement[i].setOnAction(a-> updateTxtField(txt[i],-1));
}
}
//increment text filed value
private void updateTxtField(TextField textField, int i) {
int newValue = Integer.valueOf(textField.getText()) + i;
textField.setText(String.valueOf(newValue));
}
public static void main(String[] args) { launch(args);}
}
Do not hesitate to ask for clarifications as needed. For more help, post MCVE
Upvotes: 0