在javaFX视图控制器的initialize方法中,我有一个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());
渲染列:因此该方法至少需要表列和variable属性:
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
我发现如何实现目标的语法和理解颇具挑战性,如果能得到一些建议来尝试实现解决方案,我将不胜感激。
答案 0 :(得分:2)
“传递方法”的唯一方法是创建一个包含执行此操作的逻辑的对象,或者使用方法引用。
此外,即使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
的类型更改为ObjectProperty<BigDecimal>
,则可以如下所示调用该方法。 (除了避免舍入错误,在比较值和进行其他数学运算时,BigDecimal
的操作要容易得多。)否则,您可以简单地硬编码第二个类型参数和其他功能,而只保留第一个类型方法的两个参数。
renderColumn(column, TxnObject::budgetAmountProperty, (BigDecimal val) -> val.abs().toString(), BigDecimal.ZERO);