Javafx tableview 将 cellValueFactory 内的更改绑定(bind)到表 observablelist

标签 java javafx javafx-tableview

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

创建表:

private void initCollectionTable(ObservableList<Member> mList) {

    ...

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

   ...

   collection_tbl.setItems(mlz);
}

订阅值工厂类:

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

此方法创建一个网格以在文本字段中显示成员(member)费用。因此,文本字段内的任何值更改都应该更新其自身的表 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;
}

成员(member)类:

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

最佳答案

我想我已经找到了您问题的答案。我已经简化了它,所以也许你可以用它来解决你的问题。 这是我的类(class)代码:

型号:

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

和 Controller :

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 键工作,但如果您想在更改对话框的任何字段中的值时立即更新,您可以更进一步。

关于Javafx tableview 将 cellValueFactory 内的更改绑定(bind)到表 observablelist,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47429890/

相关文章:

java - 如何填充组合框

java - 双击列标题的分隔符时不会触发 CustomResizePolicy

java - 通过 java 2D ArrayList 字符串进行矩阵搜索以查找重复实例,广度优先?

java - 解决依赖关系后使Zip任务运行

java - 404 请求的资源不可用 Eclipse/Tomcat

java - servlet 连接 mysql 时未找到类异常

Javafx - 如何将饼图从不同的类添加到 BorderPane

java - 在javafx中,我如何更改按钮的颜色,等待1秒然后将其更改回默认值?

JavaFX,如果有人选中 Tableview 中的复选框,如何触发事件