动态显示 DatePicker
Dynamically show a DatePicker
我正在编写一个 JavaFX 应用程序,它显示 table 的 StringProperty
和 ObjectPropery<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
从未出现。
我的目标是:
- 将table显示为一组Strings/LocalDates
- 假设一个单元格本身不能是 DatePicker,这是一个很好的事件处理程序,当用户想要编辑一个日期单元格时,动态 DatePicker 会出现,接受用户输入,并且值会更新。
- 确保此比例适用于 1000 行。
要自定义列的单元格,您需要在此列的 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 中包含适当的导入说明。)
我正在编写一个 JavaFX 应用程序,它显示 table 的 StringProperty
和 ObjectPropery<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
从未出现。
我的目标是:
- 将table显示为一组Strings/LocalDates
- 假设一个单元格本身不能是 DatePicker,这是一个很好的事件处理程序,当用户想要编辑一个日期单元格时,动态 DatePicker 会出现,接受用户输入,并且值会更新。
- 确保此比例适用于 1000 行。
要自定义列的单元格,您需要在此列的 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 中包含适当的导入说明。)