javafx - 如何为 JavaFX TableView 列制作通用 TableColumn 渲染器
问题描述
在 javaFX 视图控制器的初始化方法中,我有一个TableView
显示财务金额的列渲染器,每个单元格都以金额和红色或蓝色呈现,具体取决于金额是借方金额还是贷方金额。
@Override
public void initialize(URL url, ResourceBundle rb)
budgetAmountCol.setCellValueFactory(cellData -> cellData.getValue().budgetAmountProperty());
// Custom rendering of the budget amount cells in the column.
budgetAmountCol.setCellFactory((TableColumn<TxnObject, String> column) -> {
return new TableCell<TxnObject, String>() {
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
}
else {
double amt = Double.parseDouble(item);
if (amt == 0) {
setId("zero-amt");
} else {
if (amt < 0){
item = item.substring(1, item.length());
setId("debit-amt");
} else {
setId("credit-amt");
}
}
}
setText(item);
}
};
});
因为我有几列需要类似地渲染,所以我试图避免大量的源代码,并将上面的内容变成一个可以传递参数的方法,从而渲染列,比如
private void renderColumn(..) { }
占据列中表格单元格的变量在对象定义中定义,如下所示:
public class TxnObject {
..
private final StringProperty budgetAmount;
..
public String getbudgetAmount() {
double d = Double.parseDouble(budgetAmount.get());
setbudgetAmount(MainApp.formatAmount(d));
return budgetAmount.get();
}
public void setbudgetAmount(String budgetAmount) {
this.budgetAmount.set(budgetAmount);
}
public StringProperty budgetAmountProperty() {
return budgetAmount;
}
因此要求是传递代码第二行的内容,即
budgetAmountCol.setCellValueFactory(cellData -> cellData.getValue().budgetAmountProperty());
渲染列:因此该方法至少需要表列和变量属性:
private void renderColumn(TableColumn<TxnObject, String> tcol, StringProperty sprop) {
node.setCellValueFactory(..)
}
但我无法正确调用该方法。我已经尝试了以下指示结果:
renderColumn(budgetAmountCol, budgetAmountProperty());
syntax error: no method BudgetAmountProperty()
renderColumn(budgetAmountCol, cellData.getValue().budgetAmountProperty());
syntax error: Cannot find symbol CellData
renderColumn(budgetAmountCol, cellData -> cellData.getValue().budgetAmountProperty());
syntax error: StringProperty is not a functional interface
我发现如何实现我的对象的语法和理解相当具有挑战性,如果我能得到一些建议来尝试实现解决方案,我将不胜感激。
解决方案
“传递方法”的唯一方法是创建一个包含执行此操作的逻辑的对象或使用方法引用。
此外,即使 JavaFX 不强制执行这些限制,id
也应该是唯一的。改用伪类。
你可以使用
private static final PseudoClass ZERO = PseudoClass.getPseudoClass("zero-atm");
private static final PseudoClass CREDIT = PseudoClass.getPseudoClass("credit-atm");
private static final PseudoClass DEBIT = PseudoClass.getPseudoClass("debit-atm");
public static <S, T> void renderColumn(TableColumn<S, T> column,
final Callback<? super S, ObservableValue<T>> extractor, final Callback<? super T, String> converter,
final Comparator<T> comparator, final T zero) {
if (extractor == null || comparator == null || zero == null) {
throw new IllegalArgumentException();
}
column.setCellValueFactory(cd -> extractor.call(cd.getValue()));
column.setCellFactory(col -> new TableCell<S, T>() {
@Override
protected void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
pseudoClassStateChanged(ZERO, false);
pseudoClassStateChanged(CREDIT, false);
pseudoClassStateChanged(DEBIT, false);
if (empty || item == null) {
setText("");
} else {
setText(converter.call(item));
int comparison = comparator.compare(zero, item);
if (comparison == 0) {
pseudoClassStateChanged(ZERO, true);
} else {
pseudoClassStateChanged(comparison < 0 ? CREDIT : DEBIT, true);
}
}
}
});
}
public static <S, T extends Comparable<T>> void renderColumn(TableColumn<S, T> column,
Callback<? super S, ObservableValue<T>> extractor, Callback<? super T, String> converter, T zero) {
renderColumn(column, extractor, converter, Comparator.naturalOrder(), zero);
}
假设您更改了budget
to的类型,ObjectProperty<BigDecimal>
则可以调用该方法,如下所示。(BigDecimal
除了避免舍入错误之外,在比较值和进行其他数学运算时更容易使用。)否则,您可以简单地对第二个类型参数和其他功能进行硬编码,只保留该方法的前两个参数.
renderColumn(column, TxnObject::budgetAmountProperty, (BigDecimal val) -> val.abs().toString(), BigDecimal.ZERO);
推荐阅读
- node.js - 提供静态文件时从不调用节点的 get() 函数
- sql - 在 where 子句中使用一个表中的日期和另一个表中的列
- coredns - 由于属性 max_concurrent,k8s coredns pod 显示 CrashLoopBackOff
- variables - 如何创建一个帐户/标签类型的变量来存储我的用户输入?
- android-studio - 如何将图像添加到具有背景的形状按钮?
- python - np.linalg.eig 为同一矩阵给出不同的特征向量
- java - 为什么将值放在 Entry 而不是 ThreadLocal 中?
- data-visualization - 如何用图像替换行值?
- php - 如何在 Laravel 中同时使用“分页()”和清单?
- swift - Swift 生成奇数数组问题