英文:
JavaFX, how can i bind dinamically created Increment and Decrement Buttons to manipulate a specific object?
问题
I see you're working on a restaurant manager program using JavaFX and Spring Boot. You have a challenge in dynamically updating the order and quantities associated with each dish. To address this issue, you can use JavaFX properties and a more organized data structure. Here's an outline of how you can approach it:
- Create a class to represent a Dish with properties:
public class Dish {
private final StringProperty name = new SimpleStringProperty();
private final IntegerProperty quantity = new SimpleIntegerProperty(0);
public Dish(String name) {
this.name.set(name);
}
public StringProperty nameProperty() {
return name;
}
public IntegerProperty quantityProperty() {
return quantity;
}
// Getter and setter methods for name and quantity
}
- Use an
ObservableList<Dish>
to store your dishes in the controller:
private ObservableList<Dish> dishesList = FXCollections.observableArrayList();
- When populating the
TitledPane
, create aDish
instance for each dish:
for (Dish dish : dishesList) {
// Create TitledPane and other elements
// ...
// Bind the quantity TextField to the Dish quantity property
quantity.textProperty().bindBidirectional(dish.quantityProperty(), new NumberStringConverter());
// Add event handlers for plus and minus buttons to manipulate the Dish quantity
minus.setOnAction(event -> {
int value = dish.getQuantity();
if (value > 0) {
dish.setQuantity(value - 1);
}
});
plus.setOnAction(event -> {
int value = dish.getQuantity();
dish.setQuantity(value + 1);
});
// ...
}
- In your
updateOrder
method, you can now easily access the Dish associated with the TitledPane and update the order:
public void updateOrder(Dish dish, Integer quantity) {
order.put(dish, quantity);
}
This way, your Dish instances are synchronized with the GUI elements in the TitledPane, and you can update the order based on the quantity changes. Make sure to update your code accordingly to include these changes.
Remember to initialize your dishesList
with the dishes you receive from the server through your REST API. This approach should help you maintain a more organized and synchronized structure for your restaurant manager program.
英文:
I hope i will formulate this question the best i can.
I'm making a restaurant manager program for an university project using JavaFX and Springboot for my backend. Right now i'm facing a problem.
I'm implementing the 'take an order' functionality for waiters. The way it works is:
- When i load the TakeOrderView, the initialize() method uses the API REST to obtain from the server all the dishes.
- Then, i cycle through all the dishes to dinamically create TitledPanes, one for every dish, with dinamically created 'minus' and 'plus' buttons.
This is the code i used:
public void populateAccordion() {
for (Dish dish : DishesList) {
TitledPane TPDish = new TitledPane();
TPDish.setText(dish.getDishName());
// Dishes
// Name
TextFlow dishName = new TextFlow();
Text boldText = new Text("Name: ");
boldText.setFont(Font.font("Tahoma", FontWeight.BOLD, 14));
Text plainText = new Text(dish.getName());
plainText.setFont(Font.font("Tahoma", 16));
dishName.getChildren().addAll(boldText, plainText);
// Same for cost, description and allergens. I'll not show it for the sake of brevity. It's the same as above.
// Here comes the tricky part
Button minus = new Button("-");
TextField quantity = new TextField("0");
Button plus = new Button("+");
quantity.getStyleClass().add("textfield");
quantity.setPrefWidth(30);
quantity.setPrefHeight(29);
minus.getStyleClass().add("circular-button");
plus.getStyleClass().add("circular-button");
minus.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
int value = Integer.parseInt(quantity.getText());
if (value > 0) {
quantity.setText(Integer.toString(value - 1));
}
}
});
plus.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
int value = Integer.parseInt(quantity.getText());
quantity.setText(Integer.toString(value + 1));
}
});
HBox chooseQuantity = new HBox();
chooseQuantity.getChildren().addAll(minus, quantity, plus);
chooseQuantity.setSpacing(5);
VBox content = new VBox();
content.getChildren().addAll(dishName, dishCost, dishDescription, dishAllergens, chooseQuantity);
TPDish.setContent(content);
dishAccordion.getPanes().add(TPPiatto);
}
Thing is, this works, at least graphically. But i cannot use this code to manipulate an Order.
In fact, in my Controller (since i'm using an MVC pattern) i have an Order, which is a Map<Dish, Integer> to store the quantity. The behaviour i want is that when i press the 'plus' button in the "Pizza" TitledPane (for example) it "retrieves" the Dish, and calls a updateOrder(dish, quantity) method in the controller that should work in a similar way:
public void updateOrder(Dish dish, Integer quantity){
order.put(dish, quantity);
}
But the way i stuctured my code, i don't have access to the Dish stored in its TitledPane, since they are dinamically created and after the for cycle ends, i no longer have access to the 'Dish' that "corresponds" to its titledpane. I don't know how could i implement this.
Also, the 'quantity' variable is just a graphic thing right now, its not binded to the Order. I'd like that when my 'Pizza' dish in the order has a quantity of 0, the quantity shown in the titledpane is 0, and when i press '+' 3 times, the quantity in the order gets incremented, thus incrementing the quantity in the titledpane.
Please remember i'm just a University student with little to no knowledge on the best way to solve this.
答案1
得分: 1
以下是翻译好的部分:
我结构化我的代码的方式,我无法访问
Dish
这不是真的。您对for
循环中定义的当前Dish
有一个完全有效的引用。您可以在处理程序中使用该引用来调用方法:
for (Dish dish : DishesList) {
// ...
minus.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
int value = Integer.parseInt(quantity.getText());
if (value > 0) {
quantity.setText(Integer.toString(value - 1));
updateOrder(dish, value);
}
}
});
plus.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
int value = Integer.parseInt(quantity.getText());
quantity.setText(Integer.toString(value + 1));
updateOrder(dish, value);
}
});
}
希望这对您有所帮助。
英文:
> the way I structured my code, I don't have access to the Dish
This is not true. You have a perfectly valid reference to the current Dish
defined in the for
loop. You can simply call the method in the handler, using that reference:
for (Dish dish : DishesList) {
// ...
minus.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
int value = Integer.parseInt(quantity.getText());
if (value > 0) {
quantity.setText(Integer.toString(value - 1));
updateOrder(dish, value);
}
}
});
plus.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
int value = Integer.parseInt(quantity.getText());
quantity.setText(Integer.toString(value + 1));
updateOrder(dish, value);
}
});
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论