以编程方式将 LongProperty 应用于 TableColumn(相对于语义)



(在这个问题之后,这就是提示它的原因(

我有一个带有LongProperty的模型类:

public class Model { 
    private final SimpleLongProperty number = new SimpleLongProperty(this, "number"); 
    public long getNumber() { return number.get(); }
    public void setNumber(long number) { this.number.set(number); }
    public LongProperty numberProperty() { return number; }
}

现在,在我的控制器中,我有一个要绑定到此属性的TableColumn<Model, Long> colNumber。我知道我可以使用PropertyValueFactory,但是当我可以通过编程方式传递属性并让编译器/IDE对我进行拼写检查时,我不喜欢按名称赋予属性的想法。基本上我想做这样的事情(我实际上想让它更简洁,最后的例子(:

colNumber.setCellValueFactory( cdf -> cdf.getValue().numberProperty() );

但这给了我一个编译错误:

Java:不兼容的类型:lambda 表达式中的错误返回类型 javafx.beans.property.ObjectProperty 无法转换为 javafx.beans.value.ObservableValue

正如我所说,我知道我可以使用PropertyValueFactory,并且属性名称也有静态的最终字符串,但我发现它不那么优雅。有没有办法使这种程序化方法起作用?一些施法魔法?

附录:
我想制作它的实际方法是使用辅助方法:

private <S,T> Callback<CellDataFeatures<S,T>, ObservableValue<T>> propertyFactory(Callback<S, ObservableValue<T>> callback) {
    return cdf-> callback.call(cdf.getValue());
}

然后我就可以使用

colNumber.setCellValueFactory(propertyFactory(Model::numberProperty));

这使我的代码非常简洁易读,并让编译器检查我的拼写错误等。

你可以做

colNumber.setCellValueFactory( cdf -> cdf.getValue().numberProperty().asObject() );

我认为(我需要测试,但这似乎是正确的(您还可以利用模型中的自动装箱和取消装箱,并将该属性实现为ObjectProperty<Long>

public class Model { 
    private final ObjectProperty<Long> number = new SimpleObjectProperty<>(this, "number", 0L); 
    public long getNumber() { return number.get(); }
    public void setNumber(long number) { this.number.set(number); }
    public ObjectProperty<Long> numberProperty() { return number; }
}

这种方法的一个缺点是它不允许任何算术绑定,例如你不能做someValue.bind(model.numberProperty().multiply(2));等(另一个是你可能会意外调用model.numberProperty().set(null);,并造成各种破坏。

当然,另一种解决方案是使您的表列成为TableColumn<Model, Number>,但可能还有其他原因不这样做。

FWIW,我肯定会主张避免PropertyValueFactory.这是JavaFX 2.0中引入的一个方便类(即在我们有了lambda之前(,当时实现允许编译器检查的回调非常冗长。现在它基本上是多余的(恕我直言,应该弃用,或者至少应该实现您概述的那种实用方法(。

最新更新