omnomnom
omnomnom

Reputation: 302

JavaFX: what to do if you need to use a PropertyValueFactory

In my table I have one cell that does not update without interaction with the table.

I found the reason already here Java: setCellValuefactory; Lambda vs. PropertyValueFactory; advantages/disadvantages

My problem is, the default value of the cells item is LocalDate.MIN and I want my cell to contain "---" as long as the item has this default value. When I update the item, I want the cell to contain the current date string.

Item Class:

public class ItemEv {
    private final ObjectProperty<LocalDate> openedAt;

    @XmlJavaTypeAdapter(LocalDateAdapter.class)
    public final LocalDate getOpenedAt() {
        return openedAt.get();
    }
    
    public final ObjectProperty<LocalDate> openedAtProperty() {
        return this.openedAt;
    }

    public final void setOpenedAt(LocalDate openedAt) {
        this.openedAt.set(openedAt);
    }
}

in another CellFactory I set the new value: i.setOpenedAt(LocalDate.now());

this is working but not wanted:

openedAtColumnEv.setCellValueFactory(cellData -> cellData.getValue().openedAtProperty().asString());

and this is what I tried so far:

openedAtColumnEv.setCellValueFactory(new Callback<CellDataFeatures<ItemEv, String>, ObservableValue<String>>() {
    @Override
    public ObservableValue<String> call(CellDataFeatures<ItemEv, String> i) {
        if (i.getValue().getOpenedAt().equals(LocalDate.MIN)) {
            return new SimpleStringProperty("---");
        }
        return i.getValue().openedAtProperty().asString();
    }
});

and this:

openedAtColumnEv.setCellValueFactory(cellData -> {
    if(cellData.getValue().openedAtProperty().getValue().equals(LocalDate.MIN)) {
        return new SimpleStringProperty("---");
    }
    return cellData.getValue().openedAtProperty().asString();
});

Both of my tests return either SimpleStringProperty or StringBinding which should be fine.

In my tests I made a mistake where the first return in the IF statement does never return true, then the cell values show the standard string for LocalDate.MIN and get updated immediately when the item property changes.

Im a bit lost on this. Please forgive my bad english, Im not a native speaker.

Upvotes: 0

Views: 155

Answers (1)

James_D
James_D

Reputation: 209358

If the property in the model class is an ObjectProperty<LocalDate>, then the column should be a TableColumn<ItemEv, LocalDate>, not a TableColumn<ItemEv, String>.

Implementing the cellValueFactory directly (typically with a lambda expression) is always preferable to using the legacy PropertyValueFactory class. You never "need to use" a PropertyValueFactory (and never should).

The cellValueFactory is only used to determine what data to display. It is not used to determine how to display the data. For the latter, you should use a cellFactory.

So:

private TableColumn<ItemEv, LocalDate> opendAtColumnEv ;

// ...

openedAtColumnEv.setCellValueFactory(cellData -> cellData.getValue().openedAtProperty());
openedAtColumnEv.setCellFactory(column -> new TableCell<ItemEv, LocalDate>() {
    @Override
    protected void updateItem(LocalDate openedAt, boolean empty) {
        super.updateItem(openedAt, empty);
        if (openedAt == null || empty) {
            setText("");
        } else {
            if (openedAt.equals(LocalDate.MIN)) {
                setText("---");
            } else {
                // Note you can use a different DateTimeFormatter as needed
                setText(openedAt.format(DateTimeFormatter.ISO_LOCAL_DATE));
            }
        }
    }
});

Upvotes: 6

Related Questions