JavaFX,如何将动态创建的增加和减少按钮绑定到操作特定对象?

huangapple go评论59阅读模式
英文:

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:

  1. 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
}
  1. Use an ObservableList<Dish> to store your dishes in the controller:
private ObservableList<Dish> dishesList = FXCollections.observableArrayList();
  1. When populating the TitledPane, create a Dish 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);
    });

    // ...
}
  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(&quot;Name: &quot;);
                        boldText.setFont(Font.font(&quot;Tahoma&quot;, FontWeight.BOLD, 14));
                        Text plainText = new Text(dish.getName());
                        plainText.setFont(Font.font(&quot;Tahoma&quot;, 16));

                        dishName.getChildren().addAll(boldText, plainText);

                        // Same for cost, description and allergens. I&#39;ll not show it for the sake of brevity. It&#39;s the same as above.



                        // Here comes the tricky part
                        Button minus = new Button(&quot;-&quot;);
                        TextField quantity = new TextField(&quot;0&quot;);
                        Button plus = new Button(&quot;+&quot;);

                        quantity.getStyleClass().add(&quot;textfield&quot;);
                        quantity.setPrefWidth(30);
                        quantity.setPrefHeight(29);
                        minus.getStyleClass().add(&quot;circular-button&quot;);
                        plus.getStyleClass().add(&quot;circular-button&quot;);


                        minus.setOnAction(new EventHandler&lt;ActionEvent&gt;() {
                            @Override
                            public void handle(ActionEvent actionEvent) {
                                int value = Integer.parseInt(quantity.getText());
                                if (value &gt; 0) {
                                    quantity.setText(Integer.toString(value - 1));
                                    
                                }
                            }
                        });

                        plus.setOnAction(new EventHandler&lt;ActionEvent&gt;() {
                            @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&lt;ActionEvent&gt;() {
        @Override
        public void handle(ActionEvent actionEvent) {
            int value = Integer.parseInt(quantity.getText());
            if (value &gt; 0) {
                quantity.setText(Integer.toString(value - 1));

                updateOrder(dish, value);

            }
        }
    });

    plus.setOnAction(new EventHandler&lt;ActionEvent&gt;() {
        @Override
        public void handle(ActionEvent actionEvent) {
            int value = Integer.parseInt(quantity.getText());
            quantity.setText(Integer.toString(value + 1));

            updateOrder(dish, value);

        }
    });
}

huangapple
  • 本文由 发表于 2023年5月10日 23:28:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/76220224.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定