动态显示 DatePicker

Dynamically show a DatePicker

我正在编写一个 JavaFX 应用程序,它显示 table 的 StringPropertyObjectPropery<LocalDate> 值。当我深入研究 tables 的工作原理时,我似乎无法将 DatePicker 用作单元格,因此我打算将日期显示为字符串,但是当用户尝试编辑该单元格时,我捕获该事件并显示一个动态 DatePicker ,它将接受新的日期值并更新单元格。

现在,我无法显示此动态 DatePicker

Java外汇:

    <TableView fx:id="tableView" editable="true" GridPane.columnIndex="0" GridPane.rowIndex="1">
        <columns>
         ...
        <TableColumn fx:id="recDate" onEditStart="#handleChangeDate" prefWidth="100.0" text="Received Date">
            <cellValueFactory>
                <PropertyValueFactory property="recDate" />
                <!-- <DatePicker fx:id="recDatePicker" /> -->
            </cellValueFactory>
        </TableColumn>
         ...

Java 8:

@FXML
private void handleChangeDate(CellEditEvent<MissionItem, LocalDate> e) {
    final DatePicker dp = new DatePicker(e.getOldValue());
    dp.setDisable(false);
    dp.setOnAction(event -> {
        LocalDate date = dp.getValue();
        System.out.println("Selected date: " + date);
    });
    Platform.runLater(dp::show);
    dp.show(); //redundant. Still doesn't work.
    System.out.println("fired event");
}

我能够看到 fired event,但是 DatePicker 从未出现。

我的目标是:

要自定义列的单元格,您需要在此列的 cellFactory 中创建适当的 TableCell

public class DatePickerTableCell<T> extends TableCell<T, LocalDate> {

    private final DatePicker datePicker;
    private boolean listening = true;

    // listener for changes in the datepicker
    private final ChangeListener<LocalDate> listener = (observable, oldValue, newValue) -> {
        if (listening) {
            listening = false;

            TableColumn<T, LocalDate> column = getTableColumn();
            EventHandler<TableColumn.CellEditEvent<T, LocalDate>> handler = column.getOnEditCommit();
            if (handler != null) {
                // use TableColumn.onEditCommit if there is a handler
                handler.handle(new TableColumn.CellEditEvent<>(
                        (TableView<T>) getTableView(),
                        new TablePosition<T, LocalDate>(getTableView(), getIndex(), column),
                        TableColumn.<T, LocalDate>editCommitEvent(),
                        newValue
                ));
            } else {
                // otherwise check if ObservableValue from cellValueFactory is
                // also writable and use in that case
                ObservableValue<LocalDate> observableValue = column.getCellObservableValue((T) getTableRow().getItem());
                if (observableValue instanceof WritableValue) {
                    ((WritableValue) observableValue).setValue(newValue);
                }
            }

            listening = true;
        }
    };

    public DatePickerTableCell() {
        this.datePicker = new DatePicker();
        this.datePicker.valueProperty().addListener(listener);
    }

    @Override
    protected void updateItem(LocalDate item, boolean empty) {
        super.updateItem(item, empty);

        if (empty) {
            listening = false;
            setGraphic(null);
        } else {
            listening = false;
            setGraphic(this.datePicker);
            this.datePicker.setValue(item);
            listening = true;
        }
    }

    public static <E> Callback<TableColumn<E, LocalDate>, TableCell<E, LocalDate>> forTableColumn() {
        return column -> new DatePickerTableCell<>();
    }

}

请注意,此 class 不会对 "normal" 编辑状态作出反应。它始终处于编辑状态。但是,它确实尝试调用 onEditCommit 处理程序以启用对不可观察属性的处理编辑。

可以使用

通过 fxml 添加工厂
<TableColumn fx:id="recDate" prefWidth="100.0" text="Received Date">
    <cellValueFactory>
        <PropertyValueFactory property="recDate" />
    </cellValueFactory>
    <cellFactory>
         <DatePickerTableCell fx:factory="forTableColumn"/>
    </cellFactory>
</TableColumn>

(需要在 fxml 中包含适当的导入说明。)