Apply LongProperty to TableColumn programmatically (vs semantically)

(Following this question, this is what prompted)

I have a model class with 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; } } 

Now in my controller there is a TableColumn<Model, Long> colNumber , which I want to associate with this property. I know that I can use PropertyValueFactory , but I do not like the idea of ​​assigning a property by name when I can pass it programmatically, and I have a / ide compiler check. Basically I want to do something like this (I really want to make it more concise, for example, at the end):

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

but this gives me a compilation error:

java: incompatible types: invalid return type in lambda expression javafx.beans.property.ObjectProperty cannot be converted to javafx.beans.value.ObservableValue

As I said, I know that I can use PropertyValueFactory and also have static final strings for property names, but I find it less elegant. Is there any way to make this software approach work? Some kind of magic?

Application:
The actual way I wanted to do this is to use a helper method:

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

and then I can just use

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

which keeps my code very concise and readable, and the compiler checks for typos, etc.

0
source share
1 answer

You can do

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

I think (I would have to test, but it seems correct), you can also use autoboxing and unpacking in your model and implement the property as 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; } } 

One of the drawbacks of this approach is that it will not allow any of the arithmetic bindings, for example. you could not do someValue.bind(model.numberProperty().multiply(2)); etc. (The other is that you could call model.numberProperty().set(null); accidentally and damage all kinds of chaos.)

Another solution, of course, is to make the table column TableColumn<Model, Number> , but there may be other reasons not to.

FWIW, I would definitely defend PropertyValueFactory . It was a convenience class introduced in JavaFX 2.0 (i.e., before we got lambdas), when there was a lot to do with a callback that allowed the compiler to check. Now it is basically redundant (and should be deprecated, imho, or should at least implement the utility method that you draw).

+1
source

Source: https://habr.com/ru/post/1240166/


All Articles