javafx在tableview中添加所有列的所有小计

时间:2015-04-13 17:59:09

标签: javafx

我在Tableview这里允许我将价格和数量相乘并将其放入小计列我的问题是我想获得表格中所有项目的所有小计的总和,谢谢

private TableView<Product> table = new TableView<Product>();
private final ObservableList<Product> data =
        FXCollections.observableArrayList(
                new Product("Notebook", 10, 12),
                new Product("Eraser", 20, 12),
                new Product("Pencil", 30, 12),
                new Product("Pen", 40, 12),
                new Product("Glue", 50, 12));
final HBox hb = new HBox();

public static void main(String[] args) {
    launch(args);
}

@Override
public void start(Stage stage) {
    Scene scene = new Scene(new Group());
    stage.setTitle("Book Store Sample");
    stage.setWidth(650);
    stage.setHeight(550);

    final Label label = new Label("Book Store");
    label.setFont(new Font("Arial", 20));

    table.setEditable(true);


    TableColumn name = new TableColumn("Name");
    name.setMinWidth(100);
    name.setCellValueFactory(
            new PropertyValueFactory<Product, String>("name"));
    name.setCellFactory(TextFieldTableCell.forTableColumn());
    name.setOnEditCommit(
            new EventHandler<CellEditEvent<Product, String>>() {
                @Override
                public void handle(CellEditEvent<Product, String> t) {
                    ((Product) t.getTableView().getItems().get(
                            t.getTablePosition().getRow())
                    ).setName(t.getNewValue());
                }
            }
    );


    TableColumn priceCol = new TableColumn("Price");
    priceCol.setMinWidth(100);
    priceCol.setCellValueFactory(
            new PropertyValueFactory<Product, String>("price"));
    priceCol.setCellFactory(TextFieldTableCell.<Product, Number>forTableColumn(new NumberStringConverter()));
    priceCol.setOnEditCommit(
            new EventHandler<CellEditEvent<Product, Number>>() {
                @Override
                public void handle(CellEditEvent<Product, Number> t) {
                    ((Product) t.getTableView().getItems().get(
                            t.getTablePosition().getRow())
                    ).setPrice(t.getNewValue().intValue());
                }
            }
    );

    TableColumn quantityCol = new TableColumn("Quantity");
    quantityCol.setMinWidth(200);
    quantityCol.setCellValueFactory(
            new PropertyValueFactory<Product, Number>("quantity"));
    quantityCol.setCellFactory(TextFieldTableCell.<Product, Number>forTableColumn(new NumberStringConverter()));
    quantityCol.setOnEditCommit(
            new EventHandler<CellEditEvent<Product, Number>>() {
                @Override
                public void handle(CellEditEvent<Product, Number> t) {
                    ((Product) t.getTableView().getItems().get(
                            t.getTablePosition().getRow())
                    ).setQuantity(t.getNewValue().intValue());
                }
            }
    );

    TableColumn subTotalCol = new TableColumn("Sub Total");
    subTotalCol.setMinWidth(200);
    subTotalCol.setCellValueFactory(
            new PropertyValueFactory<Product, String>("subTotal"));


    table.setItems(data);
    table.getColumns().addAll(name, priceCol, quantityCol, subTotalCol);

    final TextField addName = new TextField();
    addName.setPromptText("Name");
    addName.setMaxWidth(name.getPrefWidth());
    final TextField addPrice = new TextField();
    addPrice.setMaxWidth(priceCol.getPrefWidth());
    addPrice.setPromptText("Price");
    final TextField addQuantity = new TextField();
    addQuantity.setMaxWidth(quantityCol.getPrefWidth());
    addQuantity.setPromptText("Quantity");

    final Button addButton = new Button("Add");
    addButton.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent e) {
            data.add(new Product(
                    name.getText(),
                    Integer.parseInt(addPrice.getText()),
                    Integer.parseInt(addQuantity.getText())));
            addName.clear();
            addPrice.clear();
            addQuantity.clear();
        }
    });

    hb.getChildren().addAll(addName, addPrice, addQuantity, addButton);
    hb.setSpacing(3);

    final VBox vbox = new VBox();
    vbox.setSpacing(5);
    vbox.setPadding(new Insets(10, 0, 0, 10));
    vbox.getChildren().addAll(label, table, hb);

    ((Group) scene.getRoot()).getChildren().addAll(vbox);

    stage.setScene(scene);
    stage.show();
}

public static class Product {

    private final SimpleStringProperty name;
    private final SimpleIntegerProperty price;
    private final SimpleIntegerProperty quantity;
    private final SimpleIntegerProperty subTotal;

    private Product(String name, int price, int quantity) {
        this.name = new SimpleStringProperty(name);
        this.price = new SimpleIntegerProperty(price);
        this.quantity = new SimpleIntegerProperty(quantity);
        this.subTotal = new SimpleIntegerProperty();
        NumberBinding multiplication = Bindings.multiply(this.priceProperty(), this.quantityProperty());
        this.subTotalProperty().bind(multiplication);
    }

    public String getName() {
        return name.get();
    }

    public SimpleStringProperty nameProperty() {
        return name;
    }

    public void setName(String name) {
        this.name.set(name);
    }

    public int getPrice() {
        return price.get();
    }

    public SimpleIntegerProperty priceProperty() {
        return price;
    }

    public void setPrice(int price) {
        this.price.set(price);
    }

    public int getQuantity() {
        return quantity.get();
    }

    public SimpleIntegerProperty quantityProperty() {
        return quantity;
    }

    public void setQuantity(int quantity) {
        this.quantity.set(quantity);
    }

    public int getSubTotal() {
        return subTotal.get();
    }

    public SimpleIntegerProperty subTotalProperty() {
        return subTotal;
    }

    public void setSubTotal(int subTotal) {
        this.subTotal.set(subTotal);
    }
}

}

1 个答案:

答案 0 :(得分:0)

您可以创建一个跟踪所有小计值总和的绑定:

IntegerBinding total = Bindings.createIntegerBinding(() -> 
    table.getItems().stream().collect(Collectors.summingInt(Product::getSubTotal)),
    table.getItems());

第一个参数是一个函数,用于计算product.getSubTotal()中每个元素调用table.getItems()的结果总数。第二个参数确保在table.getItems()无效时将此绑定标记为无效(因此可以重新计算)。

使用构建列表的默认机制,就像使用ObservableList<Product> data = FXCollections.observableArrayList(...)一样,列表只会在添加,删除或替换项目时失效,但如果现有subTotal则不会失效项目更改。要实现此目的,您需要修改该行以使用extractor

private final ObservableList<Product> data = FXCollections.observableList(Arrays.asList(
    new Product("Notebook", 10, 12),
    new Product("Eraser", 20, 12),
    new Product("Pencil", 30, 12),
    new Product("Pen", 40, 12),
    new Product("Glue", 50, 12)),
    product -> new Observable[] {product.subTotalProperty()});

现在你可以做类似

的事情了
Label totalLabel = new Label();
totalLabel.textProperty().bind(Bindings.format("Total: %d", total));

更新

这是IntegerBinding代码在没有lambda表达式的情况下的样子,虽然它不太清楚,我不建议这样做:

IntegerBinding total = Bindings.createIntegerBinding(new Callable<Integer>() {
    @Override
    public Integer call() {
        return table.getItems().stream().collect(Collectors.summingInt(
            new ToIntFunction<Product>() {
                @Override
                public int applyAsInt(Product product) {
                    return product.getSubTotal();
                }
            }));
    }
}, table.getItems());