Formatting an ObjectProperty<LocalDateTime> in a TableView column
Asked Answered
M

1

8

In this example, I would like for a column in my TableView to format from LocalDateTime (which is in the source data model) to the format of "yyyy/MM/dd kk:mm" in a TableColumn. (Note: For rendering, not editing) Well, I will need to work with Local/ZonedDateTime types in a few data models when displaying in table views. What is the best way to do this? (I did not notice an example of this type of capability in the Oracle Table View tutorial).

Edit-add: Or, maybe keeping the values in the data models as String (formatted), and converting to LocalDateTime for when used in processing records would be best?

import java.time.LocalDateTime;

import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;

public class Main extends Application {
    @Override
    public void start(Stage stage) {

        final ObservableList<Foo> data = FXCollections.observableArrayList();
        LocalDateTime ldt = LocalDateTime.now();
        data.add(new Foo(ldt));
        data.add(new Foo(ldt.plusDays(1)));
        data.add(new Foo(ldt.plusDays(2)));

        TableView<Foo> table = new TableView<Foo>();
        table.setItems(data);

        TableColumn<Foo, LocalDateTime> ldtCol = new TableColumn<Foo, LocalDateTime>("LDT");
        // --- Set cell factory value ---

        table.getColumns().addAll(ldtCol);
        Scene scene = new Scene(table);
        stage.setScene(scene);
        stage.show();
    } 

    public static void main(String[] args) {
        launch(args);
    }

    class Foo {
        private final ObjectProperty<LocalDateTime> ldt = 
                new SimpleObjectProperty<LocalDateTime>();

        Foo(LocalDateTime ldt) {
            this.ldt.set(ldt);
        }

        public ObjectProperty<LocalDateTime> ldtProperty() { return ldt; }
        public LocalDateTime getLdt() { return ldt.get(); }
        public void setLdt(LocalDateTime value) { ldt.set(value); }

    }
}
Mobcap answered 27/6, 2016 at 3:38 Comment(0)
T
12

You can have the TableColumn as TableColumn<Foo, LocalDateTime>: use the LocalDateTime property as value and you can define the cellFactory for the column to display it:

TableColumn<Foo, LocalDateTime> ldtCol = new TableColumn<Foo, LocalDateTime>("LDT");
ldtCol.setCellValueFactory(cellData -> cellData.getValue().ldtProperty());
ldtCol.setCellFactory(col -> new TableCell<Foo, LocalDateTime>() {
    @Override
    protected void updateItem(LocalDateTime item, boolean empty) {

        super.updateItem(item, empty);
        if (empty)
            setText(null);
        else
            setText(String.format(item.format(formatter)));
    }
});

Alternatively, you can have a DateTimeFormatter to convert the LocalDateTime into a String, but in this case table sorting will not work (will use string ordering). Thanks @JFValdes to point that out.

In this case you can use the setCellValueFactory method of TableColumn to display it as a String on the TableView.

private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd hh:mm");

...    

TableColumn<Foo, String> ldtCol = new TableColumn<Foo, String>("LDT");
ldtCol.setCellValueFactory(foo -> new SimpleStringProperty(foo.getValue().getLdt().format(formatter)));
Tentacle answered 27/6, 2016 at 6:21 Comment(4)
Just curious about one thing... With this formatting string, does the hh work the same as kk ? (I had kk, and you have hh)Mobcap
Yes, of course. Check the link of DateTimeFormatter, there you can see all of the pattern letters you can use. Also there are lots of predefined constants supported.Tentacle
You know, I was just tinkering with it, and kk allows for 24:mm time. But HH does not. So that seems different. Btw: Thank you for the assistance.Mobcap
Thanks for your answer, just point out that your first case won't sort well because TableView object treats every item as a String, not as a LocalDateTime, so it will be sorted as String.Prescript

© 2022 - 2024 — McMap. All rights reserved.