JavaFX 连续表单在网格窗格中动态添加包含内容的新行

JavaFX continuous form dynamically add new row with content in gridpane

我需要一些帮助来创建带有网格窗格的连续表单,就像在 ms 访问中一样。最初 gridpane 有 1 行和 3 列

|选择框 |删除按钮 |添加按钮 |

public class myGridpane {

    @FXML
    private GridPane gp_form;
    private List<Car> myCars = new ArrayList();

    public void initialize() {
        myCars = loadCars();
        initGridpane(myCars);
    }

    private initGridpane(List<Car> myCars) {

        int rowIndex = 0;

        for (Car myCar : myCars) {

          Button b_newCar = new Button("+");
          Button b_deleteCar = new Button("-");

          ChoiceBox<Car> cb_car = new ChoiceBox<>();
          cb_car.setItems(Car.getAllCarKeys());
          cb_car.setValue(myCar.getModel());


          b_deleteCar.setOnAction(new EventHandler<ActionEvent>() {
            @Override public void handle(ActionEvent e) {
              // remove row
              // remove car from List myCars
            }
          });

          b_newCar.setOnAction(new EventHandler<ActionEvent>() {
            @Override public void handle(ActionEvent e) {
              // add new row
            }
          });

          cb_car.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener<Number>() {

                @Override
                public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                    // update myList
                }
            });

          gp_form.add(cb_car, 0, rowIndex);
          gp_form.add(b_deleteCar, 1, rowIndex);
          gp_form.add(b_newCar, 2, rowIndex);

          rowIndex++;
        }
    }
}

结果应如下所示:

.

如何从列表中删除选择框的行和值? 如果更改了选择框,我该如何更新我的列表?

我建议使用带有自定义 ListCell 的 ListView 而不是 GridPane,因为您的汽车列表可能包含例如 1k 个值。在这种情况下,您将在 GridPane 中创建 3k 个节点,这会降低性能。 ListView 将只创建可见的单元格并在需要时重用它们。

试试这个代码:

private ObservableList<Car> cars = FXCollections.observableArrayList();

@Override
public void start(Stage primaryStage) {
    cars.addAll(new Car(CAR_TYPE.CAR1), new Car(CAR_TYPE.CAR2), new Car(CAR_TYPE.CAR3));

    ListView<Car> carsListView = new ListView<>();
    carsListView.setCellFactory(c -> new CarListCell());
    carsListView.setItems(cars);

    StackPane root = new StackPane();
    root.getChildren().add(carsListView);

    Scene scene = new Scene(root, 300, 250);

    primaryStage.setTitle("Cars list view");
    primaryStage.setScene(scene);
    primaryStage.show();
}

private class CarListCell extends ListCell<Car> {

    private HBox content = new HBox();
    private ChoiceBox<CAR_TYPE> cb = new ChoiceBox<>();
    private Button add = new Button("+");
    private Button sub = new Button("-");

    public CarListCell() {
        cb.setItems(FXCollections.observableArrayList(CAR_TYPE.values()));
        cb.setMaxWidth(Double.MAX_VALUE);
        HBox.setHgrow(cb, Priority.ALWAYS);
        content.getChildren().addAll(cb, add, sub);
        content.setSpacing(10);
        setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
        setGraphic(content);
    }

    @Override
    protected void updateItem(Car item, boolean empty) {
        super.updateItem(item, empty);
        if (item == null || empty) {
            setText(null);
            setGraphic(null);
        } else {
            setGraphic(content);
            cb.setValue(item.getType());
            add.setOnAction(e -> {
                Car newCar = new Car(cb.getValue());
                cars.add(newCar);
            });
            sub.setOnAction(e -> {
                cars.remove(item);
            });
        }
    }

}

private enum CAR_TYPE {
    CAR1, CAR2, CAR3;
}

private class Car {

    private CAR_TYPE type;

    public Car(CAR_TYPE type) {
        this.type = type;
    }

    public CAR_TYPE getType() {
        return type;
    }

    public void setType(CAR_TYPE type) {
        this.type = type;
    }
}

我添加了第二个下拉菜单和一个保存按钮,并用一个空的初始列表更改了开始。这工作正常,但是当我单击保存按钮时,如何将所有 selected 汽车及其颜色添加到 ArrayList 中?

如果我 select 第一辆车的颜色没有点击“+”按钮,ObservableList 是空的。

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class Main extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }

    private ObservableList<Car> cars = FXCollections.observableArrayList();

    @Override
    public void start(Stage primaryStage) {

        Car initialCar = new Car(null,null);

        cars.add(initialCar);

        ListView<Car> carsListView = new ListView<>();
        carsListView.setCellFactory(c -> new CarListCell());
        carsListView.setItems(cars);

        StackPane root = new StackPane();
        root.getChildren().addAll(carsListView, new Button("Save"));

        Scene scene = new Scene(root, 300, 250);

        primaryStage.setTitle("Cars list view");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private class CarListCell extends ListCell<Car> {

        private HBox content = new HBox();
        private ChoiceBox<CAR_TYPE> cb_car = new ChoiceBox<>();
        private ChoiceBox<CAR_COLOR> cb_color = new ChoiceBox<>();
        private Button add = new Button("+");
        private Button sub = new Button("-");

        public CarListCell() {

            cb_car.setItems(FXCollections.observableArrayList(CAR_TYPE.values()));
            cb_color.setItems(FXCollections.observableArrayList(CAR_COLOR.values()));

            HBox.setHgrow(cb_car, Priority.ALWAYS);
            HBox.setHgrow(cb_color, Priority.ALWAYS);

            content.getChildren().addAll(cb_car, cb_color, add, sub);
            content.setSpacing(10);
            setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
            setGraphic(content);
        }

        @Override
        protected void updateItem(Car item, boolean empty) {
            super.updateItem(item, empty);
            if (item == null || empty) {
                setText(null);
                setGraphic(null);
            } else {
                setGraphic(content);
                cb_car.setValue(item.getType());
                cb_color.setValue(item.getColor());
                add.setOnAction(e -> {
                    Car newCar = new Car(cb_car.getValue(), cb_color.getValue());
                    cars.add(newCar);
                });
                sub.setOnAction(e -> {
                    cars.remove(item);
                });
            }
        }

    }

    private enum CAR_TYPE {
        CAR1, CAR2, CAR3;
    }

    private enum CAR_COLOR {
        BLUE, RED, GREEN;
    }

    private class Car {

        private CAR_TYPE type;
        private CAR_COLOR color;

        public Car(CAR_TYPE type, CAR_COLOR color) {
            this.type = type;
            this.color = color;
        }

        public CAR_TYPE getType() {
            return type;
        }

        public void setType(CAR_TYPE type) {
            this.type = type;
        }

        public CAR_COLOR getColor() {
            return color;
        }

        public void setColor(CAR_COLOR color) {
            this.color = color;
        }
    }
}