动态显示DatePicker

时间:2018-01-04 21:42:57

标签: java swing javafx datepicker javafx-8

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

现在,我无法让这个动态DatePicker显示出来。

JavaFX的:

    <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永远不会出现。

我的目标是:

  • 将表格显示为一组字符串/本地日期
  • 假设一个单元格本身不能是一个DatePicker,那么很好的事件处理程序,当用户想要编辑日期单元格时,动态DatePicker会显示,接受用户输入,并且值会更新。
  • 确保此比例为1000行。

1 个答案:

答案 0 :(得分:1)

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

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<>();
    }

}

请注意,此类不会对“正常”编辑状态做出反应。它始终处于编辑状态。但是,它确实调用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中。)