java - 如何将 TableView 内的 TableColumn 总和绑定到外部标签 textProperty()?
问题描述
有一个订单表视图,其中有一列用于表示订单成本。Order 对象的成本属性可以在 TableView 中更改。这意味着 Order 列单元格可以使用 TextFieldTableCell 进行更改。此外,TableView 之外还有一个标签,它应该代表订单成本的总和。现在,问题是我不知道如何将订单成本列的总和绑定到标签的文本属性()。
这里有一段代码可以澄清问题:
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);
解决方案
您可以执行以下操作:
创建一个
ObservableList
到 的extractor
映射costProperty()
,并将其用作表的items
列表:tableView.setItems(FXCollections.observableArrayList( order -> new Observable[] { order.costProperty() }));
这确保列表在列表的任何
costProperty
元素发生更改时触发更新事件(除了在列表中添加或删除元素时触发的通常事件等)创建一个
DoubleBinding
绑定到列表的,并计算总成本:DoubleBinding totalCost = Bindings.createDoubleBinding(() -> { double total = 0 ; for (Order order : tableView.getItems()) { total = total + order.getCost(); } return total ; }, tableView.getItems());
将标签绑定
textProperty()
到总成本:totalCostLabel.textProperty().bind(totalCost.asString());
如果您想更好地控制它的显示方式,您可以向该方法format
提供a 。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();
}
}
推荐阅读
- python-3.x - 为什么 print('a' > 'b') 为假而 print('a' > 'A') 为真?
- javascript - Javascript用自身的绑定版本替换函数是否不好
- amazon-web-services - AWS S3 无法使用预签名 URL 检索文档:无效日期(应该是自纪元以来的秒数)
- java - 异常:原因:org.springframework.beans.factory.BeanCreationException:创建名为“httpPutFormContentFilter”的bean时出错
- ios - 未从 firebase 添加 TableView 事件
- python-3.x - AttributeError:“模块”对象没有“累积”属性
- mysql - 如何比较日期时间并获取第一个和最后一个日期 MySQL
- javascript - 关于 javascript document.getElementsByClassName() 的查询
- c - 为什么 system("clear") 命令无法按预期方式工作?
- c - 系统调用表中常见的abi有什么用