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;
}
}
}
我需要一些帮助来创建带有网格窗格的连续表单,就像在 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;
}
}
}