Getting LocalDate to display in a Tableview in Javafx

后端 未结 1 836
-上瘾入骨i
-上瘾入骨i 2020-12-21 08:25

I have been working on part of my application that allows a user to input holidays that their school takes off and saves it to a file. The name of the holiday and the date (

相关标签:
1条回答
  • 2020-12-21 09:03

    TL;DR version: you are confusing the cellValueFactory with the cellFactory. See, for example, this tutorial for a nice explanation of the difference, which is summarized for this particular example below.

    A table column's cellValueFactory is an object that tells the column which values to display in the cells, or more precisely how to get those values from the objects representing each row. This is represented by a Callback<CellDataFeatures<Holiday, LocalDate>, ObservableProperty<LocalDate>>, i.e. a function mapping a CellDataFeatures<Holiday, LocalDate> to an ObservableValue<LocalDate>. So in Java code you would do

    dateColumn.setCellValueFactory(holidayRowData -> holidayRowData.getValue().dateProperty());
    

    or, if you prefer to use the (somewhat legacy) PropertyValueFactory class, you can do

    dateColumn.setCellValueFactory(new PropertyValueFactory<>("date"));
    

    The latter version has the (many disadvantages, but the one) advantage that it can be done in FXML as well. Note, though, that you want the cellValueFactory, not the cellFactory. So your FXML should be

    <TableView fx:id="tableView">
        <columnResizePolicy>
            <TableView fx:constant="CONSTRAINED_RESIZE_POLICY"/>
        </columnResizePolicy>
        <columns>
            <TableColumn text="Holiday Name">
                <cellValueFactory>
                    <PropertyValueFactory property="name"/>
                </cellValueFactory>
            </TableColumn>
            <TableColumn text="Date">
                <cellValueFactory>
                    <PropertyValueFactory property="date" />
                </cellValueFactory>
            </TableColumn>
        </columns>
    </TableView>
    

    The cellFactory, by contrast, is an object that tells the column how to display the data. It is represented by a Callback<TableColumn<Holiday, LocalDate>, TableCell<Holiday, LocalDate>>, i.e a function mapping a TableColumn<Holiday, LocalDate> to a TableCell<Holiday, LocalDate>. The ClassCastException occurs because the cell factory you set is going to be passed the TableColumn, but is expecting to receive a CellDataFeatures, and so when it tries to treat it as such, the cast fails.

    You may well want a cell factory here, in addition to the cell value factory, so that you can control how the date is displayed (e.g. control the format used for it). If you give the date column an fx:id, say <TableColumn fx:id="dateColumn">, and inject it into the controller with

    @FXML
    private TableColumn<Holiday, LocalDate> dateColumn ;
    

    then in the controller's initialize method, you can do:

    public void initialize() throws IOException {
        data = new HolidayData();
        data.loadHolidays();
        tableView.setItems(data.getHolidays());
    
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
        dateColumn.setCellFactory(column -> new TableCell<Holiday, LocalDate>() {
            @Override
            protected void updateItem(LocalDate date, boolean empty) {
                super.updateItem(date, empty);
                if (empty) {
                    setText("");
                } else {
                    setText(formatter.format(date));
                }
            }
        });
    }
    
    0 讨论(0)
提交回复
热议问题