JavaFX Tableview - 依赖于其他列的列值

时间:2015-04-12 12:01:38

标签: javafx

我在JavaFX中有一个TableView。它有一个字段subTotal,它取决于字段quantityprice的值。我为subTotal添加了一个新列。

我有文本字段可以向表中添加新行。但是,添加按钮希望为textfield添加另一个subTotal,尽管对于小计列并不是必需的。

到目前为止我尝试过:

TableColumn columnCodeProduct = new TableColumn("Product Code");
columnCodeProduct.setMinWidth(100);
columnCodeProduct.setCellValueFactory(new PropertyValueFactory<Data , Integer>("productname "));

TableColumn columnProductName = new TableColumn("Product Name");
columnProductName.setMinWidth(140);
columnProductName.setCellValueFactory(new PropertyValueFactory<Data , String>("codeproduct"));

TableColumn columnPrice = new TableColumn("Price");
columnPrice.setMinWidth(100);
columnPrice.setCellValueFactory(new PropertyValueFactory<Data , Integer>("price"));

TableColumn columQuantity = new TableColumn("Quantity");
columQuantity.setMinWidth(100);
columQuantity.setCellValueFactory(new PropertyValueFactory<Data , Integer>("quantity"));


TableColumn columnTotal = new TableColumn("Sub Total");
columnTotal.setMinWidth(100);
columQuantity.setCellValueFactory(new PropertyValueFactory<Data , Integer>("sub"));

tableData.getColumns().addAll(columnCodeProduct , columnProductName , columnPrice ,  columQuantity );

tableData.setItems(data);


addButton = new Button("Add Item");


addButton.setOnAction(new EventHandler<ActionEvent>() {

    @Override
    public void handle(ActionEvent event)
    {
        if(addproCodeTextfield.getText().isEmpty() || addproNameTextfield.getText().isEmpty()
            || addPriceTextfield.getText().isEmpty() || quantityTextField.getText().isEmpty())
        {
            System.out.println("Please Add information to all the fields");
        } else {
            data.add(new Data (

                           addproCodeTextfield.getText(),
                           addproNameTextfield.getText(),
                 addPriceTextfield.getText(),                             
                           quantityTextField.getText()));                             
             methodTotal();
        }
    }
});

数据类

public class Data
{
    private final SimpleStringProperty codeproduct;
    private final SimpleStringProperty productname;
    private final SimpleStringProperty price ;
    private final SimpleStringProperty quantity;



    public Data (String code , String proname ,  String presyo ,  String quant )
    {
        this.codeproduct = new SimpleStringProperty(code);
        this.productname = new SimpleStringProperty(proname);
        this.price = new SimpleStringProperty(presyo);
        this.quantity = new SimpleStringProperty(quant);

    }

    public String getcodeProduct()
    {
        return codeproduct.get();
    }

    public String getproductName()
    {
        return productname.get();
    }

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

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

}

2 个答案:

答案 0 :(得分:6)

我会像@ItachiUchiha建议的那样重组你的模型类。如果您认为需要使用String表示形式保存数据,则只需为subtotal列创建绑定:

TableColumn<Data, Number> subtotalColumn = new TableColumn<>("Sub Total");
subTotalColumn.setCellValueFactory(cellData -> {
    Data data = cellData.getValue();
    return Bindings.createDoubleBinding(
            () -> {
                try {
                    double price = Double.parseDouble(data.getPrice());
                    int quantity = Integer.parseInt(data.getQuantity());
                    return price * quantity ;
                } catch (NumberFormatException nfe) {
                    return 0 ;
                }
            },
            data.priceProperty(),
            data.quantityProperty()
    );
});

答案 1 :(得分:5)

您可以从JavaFX的权力中获益bind

在实施上述方案时,很少有人要注意:

  • POJO类(在您的情况下为Data)字段必须具有正确的类型。例如,价格和数量必须为SimpleIntegerProperty而不是SimpleStringProperty。这有助于我们使用Bindings
  • SubTotal字段取决于价格和数量的。实现此目标的最佳方法是绑定 subTotalProperty to a multiply Binding of price and quantity

我创建了一个(不那么)简单示例基本可编辑的tableview 来显示该方法。它有其他功能,如可编辑单元格,您(或其他寻求相同问题的人)可能需要;)

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.NumberBinding;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.converter.NumberStringConverter;

public class TableViewSample extends Application {

    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);
        }
    }
}

<强>截图

enter image description here

注意 - 我已为每个列定义了setCellFactorysetOnCommit。这是因为名称,价格和数量列为editable。如果您不寻求可编辑的属性,欢迎您将其删除。