Javafx tableview将cellValueFactory中的更改绑定到表observablelist

时间:2017-11-22 08:24:47

标签: java javafx javafx-tableview

我有javafx表,其中包括一个组织的成员月度费用。在此表中,我显示了一些默认金额的费用,以便在任何情况下用户都可以更新金额,或者按原样继续。我真正需要的是如果用户更新任何值,那些应立即绑定到表observablelist。

创建表格

private void initCollectionTable(ObservableList<Member> mList) {

    ...

    total_pay_col.setCellValueFactory(new SubscriptionValueFactory());
    detail_view_col.setCellValueFactory(new DisplaySubscriptionFactory());

   ...

   collection_tbl.setItems(mlz);
}

SubscriptionValueFactory类:

public class SubscriptionValueFactory implements Callback<TableColumn.CellDataFeatures<Member, String>, ObservableValue<String>> {

    @Override
    public ObservableValue<String> call(TableColumn.CellDataFeatures<Member, String> param) {

        //Here Subscriptions are equal to various member charges
        Member ml = param.getValue();
        List<MemberSubscriptions> mbrSubs = new ArrayList<>(ml.getMemberSubscriptions());
        double sum =mbrSubs.stream().mapToDouble(a -> a.getAmount()).sum();
        return new SimpleObjectProperty<>(TextFormatHandler.CURRENCY_DECIMAL_FORMAT.format(sum));
    }

}

DisplaySubscriptionFactory类

public class DisplaySubscriptionFactory implements Callback<TableColumn.CellDataFeatures<Member, Button>, ObservableValue<Button>> {

    @Override
    public ObservableValue<Button> call(TableColumn.CellDataFeatures<Member, Button> param) {
        Member ml = param.getValue();

        List<MemberSubscriptions> mbrSubs = new ArrayList<>(ml.getMemberSubscriptions());

        double sum =mbrSubs.stream().mapToDouble(a -> a.getAmount()).sum();
        boolean flag = // SOME BOOLEAN CHECK HERE-----

        param.getValue().setTotalSubscription(sum);
        Button button = new Button("View Info");
        button.setOnAction((evt) -> {
            Alert alert_details = new Alert(Alert.AlertType.INFORMATION);
            alert_details.setTitle("Subscription Information");
            alert_details.setHeaderText("Member Subscription information for each installment");
            alert_details.getDialogPane().setContent(createContentGrid(mbrSubs, sum, flag));
            alert_details.show();
        });

        return new SimpleObjectProperty<>(button);
    }

此方法创建一个网格,以显示文本字段中的成员费用。因此,文本字段内的任何值更改都应更新表 observablelist 的属性。

private Node createContentGrid(List<MemberSubscriptions> mbrSubs, double sum, boolean flag) {

    GridPane grid = new GridPane();
    grid.setHgap(20);
    grid.setVgap(10);
    grid.setPadding(new Insets(20, 20, 10, 10));

    Label totLabel = new Label(TextFormatHandler.CURRENCY_DECIMAL_FORMAT.format(sum));
    totLabel.setFont(Font.font("System Bold", 21.0));
    Label col_h_1 = new Label("Subscription");
    col_h_1.setFont(Font.font("System Bold", 17.0));
    Label col_h_2 = new Label("Amount");
    col_h_2.setFont(Font.font("System Bold", 17.0));

    grid.add(col_h_1, 0, 0);
    grid.add(col_h_2, 1, 0);
    Label[] labels = new Label[mbrSubs.size()];
    TextField[] fields = new TextField[mbrSubs.size()];
    for (int i = 0; i < mbrSubs.size(); i++) {
        MemberSubscriptions get = mbrSubs.get(i);
        labels[i] = new Label("label");
        fields[i] = new TextField();
        fields[i].setTextFormatter(TextFormatHandler.currencyFormatter());
        labels[i].setText(get.getMemberSubscription().getFeeName());
        fields[i].setText(TextFormatHandler.CURRENCY_DECIMAL_FORMAT.format(get.getAmount()));
        grid.add(labels[i], 0, i + 1);
        grid.add(fields[i], 1, i + 1);
    }
    grid.add(totLabel, 1, mbrSubs.size() + 1);
    return grid;
}

会员类:

public class Member {
    private Integer id;
    private String memberId;
    ...
    private Set<MemberSubscriptions> memberSubscriptions = new HashSet<>();
    ...

MemberSubscriptions类

public class MemberSubscriptions {
    private Integer id;
    private Member member;
    private Double amount;
    ...

enter image description here

1 个答案:

答案 0 :(得分:1)

我想我找到了你问题的答案。我简化了它,所以也许你可以用它来解决你的问题。 这是我的课程代码:

型号:

public class Model {

    private LongProperty id;
    private DoubleProperty amount;
    private ObjectProperty<SubModel> subModel;

    public Model(Long id, Double amount, SubModel subModel) {
        this.id = new SimpleLongProperty(id);
        this.amount = new SimpleDoubleProperty(amount);
        this.subModel = new SimpleObjectProperty<>(subModel);
    }

    public long getId() {
        return id.get();
    }

    public LongProperty idProperty() {
        return id;
    }

    public DoubleProperty amountProperty() {
        return amount;
    }

    public SubModel getSubModel() {
        return subModel.get();
    }

    public ObjectProperty<SubModel> subModelProperty() {
        return subModel;
    }
}

子模型:

public class SubModel {

    private LongProperty id;
    private DoubleProperty xAmount;
    private DoubleProperty yAmount;

    public SubModel(Long id, Double xAmount, Double yAmount) {
        this.id = new SimpleLongProperty(id);
        this.xAmount = new SimpleDoubleProperty(xAmount);
        this.yAmount = new SimpleDoubleProperty(yAmount);
    }

    public long getId() {
        return id.get();
    }


    public double getxAmount() {
        return xAmount.get();
    }

    public DoubleProperty xAmountProperty() {
        return xAmount;
    }

    public double getyAmount() {
        return yAmount.get();
    }

    public DoubleProperty yAmountProperty() {
        return yAmount;
    }
}

按钮单元格:

public class ButtonTableCell<S, T> extends TableCell<S, T> {

    private Button button;

    public ButtonTableCell() {
        this.button = new Button("View Info");
        button.setOnAction(event -> {
            Model model = (Model) getTableRow().getItem();
            Dialog<SubModel> dialog = new AmountDialog(model.getSubModel());
            dialog.getDialogPane().getButtonTypes().add(ButtonType.OK);
            dialog.showAndWait().ifPresent(result -> {
                model.amountProperty().set(result.getxAmount() + result.getyAmount());
            });
        });
    }

    @Override protected void updateItem(T item, boolean empty) {
        super.updateItem(item, empty);
        setText(null);
        if (empty) {
            setGraphic(null);
        } else {
            setGraphic(button);
        }
    }
}

对话框:

public class AmountDialog extends Dialog<SubModel> {

    public AmountDialog(SubModel model) {
        setTitle("Title");
        setHeaderText("Header");
        getDialogPane().setContent(createContent(model));
        setResultConverter(button -> {
            if (button == ButtonType.OK) {
                return model;
            }
            return null;
        });
    }

    private GridPane createContent(SubModel model) {
        GridPane grid = new GridPane();
        grid.setHgap(20);
        grid.setVgap(10);
        grid.setPadding(new Insets(20, 20, 10, 10));
        Label sub = new Label("Sub");
        Label amount = new Label("Amount");

        Label amountX = new Label("AmountX");
        Label amountY = new Label("AmountY");

        TextField tfAmounX = new TextField(String.valueOf(model.getxAmount()));
        TextField tfAmountY = new TextField(String.valueOf(model.getyAmount()));

        Bindings.bindBidirectional(tfAmounX.textProperty(), model.xAmountProperty(), new StringDoubleConverter());
        Bindings.bindBidirectional(tfAmountY.textProperty(), model.yAmountProperty(), new StringDoubleConverter());

        grid.add(sub, 0, 0);
        grid.add(amount, 1, 0);

        grid.add(amountX, 0, 1);
        grid.add(tfAmounX, 1, 1);

        grid.add(amountY, 0, 2);
        grid.add(tfAmountY, 1, 2);

        return grid;
    }

    private class StringDoubleConverter extends StringConverter<Number> {
        @Override public String toString(Number object) {
            return object.toString();
        }

        @Override public Number fromString(String string) {
            // You may handle NumberFormatException.
            return Double.valueOf(string);
        }
    }
}

和控制器:

public class Controller implements Initializable {

    @FXML
    private TableView<Model> table;
    @FXML
    private TableColumn<Model, Long> colId;
    @FXML
    private TableColumn<Model, Double> colAmount;
    @FXML
    private TableColumn<Model, SubModel> colInfo;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        setupTable();
        setupData();
    }

    private void setupTable() {
        colId.setCellValueFactory(data -> data.getValue().idProperty().asObject());
        colAmount.setCellValueFactory(data -> data.getValue().amountProperty().asObject());
        colInfo.setCellValueFactory(data -> data.getValue().subModelProperty());

        colInfo.setCellFactory(factory -> new ButtonTableCell<>());
    }

    private void setupData() {
        SubModel firstSubModel = new SubModel(1L, 0D, 0D);
        SubModel secondSubModel = new SubModel(2L, 0D, 0D);

        Model fist = new Model(1L, 0D, firstSubModel);
        Model second = new Model(2L, 0D, secondSubModel);

        ObservableList<Model> tableData = FXCollections.observableArrayList();
        tableData.add(fist);
        tableData.add(second);

        table.setItems(tableData);
    }
}

我知道答案有点长,但我希望它能解决你的问题。对我来说,它正在OK按下,但如果你想在对话框的任何字段中更改值时立即更新,你可以更进一步。