Issue
today i encountered another thing i don't really understand while trying to learn more about JavaFX and Java in general.
Reference is the following tutorial (im trying to apply the principle to an organizer):
href="http://code.makery.ch/library/javafx-8-tutorial/part3/" rel="nofollow noreferrer">JavaFX 8 Tutorial
I will give a short outline of the particular part on which i've got a question:
My main window contains a tableview which shows some appointment-data. So i got some lines of this style(same as in the tutorial):
aColumn.setCellValueFactory(cellData ->cellData.getValue().getAColumnsProperty());
The data can be manipulated via an additional EditDialog. That works just fine. If i edit things the changes are displayed immediately but i did some additional research to better understand the Lambda (not too successful). Now...in the online java documentation Java Doc PropertyValueFactory it says: "A convenience implementation of the Callback-Interface,[...]"
So i refactored my code into this style:
aColumn.setCellValueFactory(new PropertyValueFactory<Appointment,LocalDate>("date"));
Which i find much more readable than the Lambda. But i noticed that when i make changes i need to do some sorting on the TableView before the changes are displayed.
Is it possible to achieve an immediate display of change in the second approach?
If yes: are there major disavantages which would discourage such a modification? I.e. would the Lambda be the best practice in this situation?
I appreciate any help.
Solution
PropertyValueFactory
expects correctly named property getters. getAColumnsProperty
is probably not one.
In case of new PropertyValueFactory<Appointment, LocalDate>("date")
the Appointment
class needs to contain a dateProperty()
method; the returned values need to extend ReadOnlyProperty
for this to work and any edits will only lead to an update in the model automatically, if the returned object also WritableValue
.
Example Appointment
class that should work with PropertyValueFactory<>("date")
:
public class Appointment {
private final ObjectProperty<LocalDate> date = new SimpleObjectProperty<>();
public final LocalDate getDate() {
return this.date.get();
}
public final void setDate(LocalDate value) {
this.date.set(value);
}
public final ObjectProperty<LocalDate> dateProperty() {
return this.date;
}
}
If no such method exists, PropertyValueFactory
will use a getter to retrieve the value, i.e. getDate()
, but this case updates in the model will not be visible in the UI until it updates the Cell
, since the PropertyValueFactory
"does not know" where to add a listener.
Disadvantages of PropertyValueFactory
- Can only find
public
methods in apublic
class PropertyValueFactory
uses reflection- Not typesafe. In
new PropertyValueFactory<Appointment, LocalDate>("date")
the compiler does not check, if there is a appropriate method, if that method even returns a suitable class or if e.g. the property getter returns aString
instead of aReadOnlyProperty<LocalDate>
which can lead toClassCastException
s. - No compile time checking. In the lambda expression the compiler can do some checking if the method exists and returns a appropriate type; with
PropertyValueFactory
this is not done. - Does not work with records.
If you are sure to implement the appropriate methods in the item class correctly, there is nothing wrong with using PropertyValueFactory
, but as mentioned above it has it's disadvantages. Moreover implementing the Callback
is much more flexible. You could e.g. do some additional modifications:
TableColumn<Appointment, String> column = ...
column.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Appointment, String>, ObservableValue<String>> {
@Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<Appointment, String> cd) {
Appointment a = cd.getValue();
return Bindings.createStringBinding(() -> "the year: " + a.getDate().getYear(), a.dateProperty());
}
});
Answered By - fabian
Answer Checked By - Mildred Charles (JavaFixing Admin)