Как связать сумму TableColumn внутри TableView с внешней меткой textProperty ()? - PullRequest
0 голосов
/ 01 мая 2020

Существует TableView заказов, в котором есть столбец для представления стоимости заказа. Свойство cost объекта Order можно изменить в TableView. Это означает, что ячейки столбца Order могут быть изменены с помощью TextFieldTableCell. Кроме того, вне TableView есть метка, которая должна представлять сумму затрат на заказы. Теперь проблема в том, что я не знаю, как связать столбец суммы затрат на заказ со свойством text () в Label.

Вот фрагмент кода для решения проблемы:

     class Order {
            private SimpleStringProperty name;
            private SimpleIntegerProperty cost;

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

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

            public SimpleStringProperty nameProperty() {
                return this.name;
            }

            public Integer getCost() {
                return this.cost.get();
            }

            public void setCost(Integer cost) {
                this.cost.set(cost);
            }

            public SimpleIntegerProperty costProperty() {
                return this.cost;
            }
        }

        TableView<Order> tableView = new TableView<>();

        TableColumn<Order, String> nameColumn = new TableColumn<>();
        nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
        nameColumn.setCellFactory(TextFieldTableCell.forTableColumn());

        TableColumn<Order, String> costColumn = new TableColumn<>();
        costColumn.setCellValueFactory(new PropertyValueFactory<>("cost"));
        costColumn.setCellFactory(TextFieldTableCell.forTableColumn());

        tableView.getColumns().addAll(nameColumn, costColumn);

        Label totalCostLabel = new Label("Total cost should be updated in this label");

        VBox vBox = new VBox();
        vBox.getChildren().addAll(tableView, totalCostLabel);

1 Ответ

2 голосов
/ 01 мая 2020

Вы можете сделать следующее:

  1. Создать ObservableList с сопоставлением extractor с costProperty() и использовать его в качестве таблицы items list:

    tableView.setItems(FXCollections.observableArrayList(
        order -> new Observable[] { order.costProperty() }));
    

    Это гарантирует, что список запускает события обновления, если какой-либо из costProperty элементов списка изменяется (в дополнение к обычным событиям, запускаемым, если элементы добавляются или удаляются из список, et c.)

  2. Создайте DoubleBinding, который привязывается к списку и рассчитывает общую стоимость:

    DoubleBinding totalCost = Bindings.createDoubleBinding(() -> {
        double total = 0 ;
        for (Order order : tableView.getItems()) {
            total = total + order.getCost();
        }
        return total ;
    }, tableView.getItems());
    
  3. Привязать textProperty() этикетки к общей стоимости:

    totalCostLabel.textProperty().bind(totalCost.asString());
    

Вы можете указать format для метода asString(), если Вы хотите больше контроля над тем, как он отображается.

Вот полный пример, адаптированный из вашего кода:

import javafx.application.Application;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.DoubleBinding;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.converter.IntegerStringConverter;


public class SummingTable extends Application {


    @Override
    public void start(Stage stage) {
        TableView<Order> tableView = new TableView<>();

        tableView.setItems(FXCollections.observableArrayList(
                order -> new Observable[] { order.costProperty() }));

        tableView.getItems().addAll(
                new Order("Order 1", 10),
                new Order("Order 2", 20));

        tableView.setEditable(true);


        TableColumn<Order, String> nameColumn = new TableColumn<>();
        nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
        nameColumn.setCellFactory(TextFieldTableCell.forTableColumn());

        TableColumn<Order, Integer> costColumn = new TableColumn<>();
        costColumn.setCellValueFactory(cellData -> cellData.getValue().costProperty().asObject());
        costColumn.setCellFactory(TextFieldTableCell.forTableColumn(new IntegerStringConverter()));

        tableView.getColumns().addAll(nameColumn, costColumn);

        Label totalCostLabel = new Label("Total cost should be updated in this label");

        DoubleBinding totalCost = Bindings.createDoubleBinding(() -> {
            double total = 0 ;
            for (Order order : tableView.getItems()) {
                total = total + order.getCost();
            }
            return total ;
        }, tableView.getItems());

        totalCostLabel.textProperty().bind(totalCost.asString());

        VBox vBox = new VBox();
        vBox.getChildren().addAll(tableView, totalCostLabel);

        Scene scene = new Scene(vBox);
        stage.setScene(scene);
        stage.show();

    }

    public class Order {
        private final StringProperty name = new SimpleStringProperty();
        private final IntegerProperty cost = new SimpleIntegerProperty();

        public Order(String name, int cost) {
            setName(name);
            setCost(cost);
        }

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

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

        public StringProperty nameProperty() {
            return this.name;
        }

        public Integer getCost() {
            return this.cost.get();
        }

        public void setCost(Integer cost) {
            this.cost.set(cost);
        }

        public IntegerProperty costProperty() {
            return this.cost;
        }
    }

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

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...