例如,当您按下回车键时,TextFieldTableCell会响应并调用commitEdit()。
如果我使用自定义节点进行显示,那么我该如何监听确认编辑的方法?例如,我有一个扩展VBox的DateTimePicker。我无法将KeyListener添加到VBox。
如何查看表内编辑确认,我该怎么办?以下是我的尝试:
class TableCellDateTimePicker extends TableCell<CHILD, LocalDateTime> {
public TableCellDateTimePicker() {
super();
}
@Override
public void startEdit() {
super.startEdit();
DateTimePicker picker = new DateTimePicker();
picker.getDatePickerField().setOnKeyPressed((KeyEvent event) -> {
System.out.println("PRESS");
if (event.getCode() == KeyCode.ENTER) {
commitEdit(picker.getValue());
}
});
picker.setValue(getItem());
setGraphic(picker);
}
@Override
public void commitEdit(LocalDateTime newValue) {
super.commitEdit(newValue);
setText(newValue.toString());
}
@Override
public void cancelEdit() {
super.cancelEdit();
}
}
的DateTimePicker:
/**
* A custom DateTimePicker that lets a user select a LocalDateTime.
*
* @author Toni-Tran
*/
public class DateTimePicker extends VBox {
@FXML
private DatePicker datePicker;
@FXML
private Button showTimePickerBtn;
private NumberPicker hourField;
private NumberPicker minuteField;
private ObjectProperty<LocalDateTime> currentLocalDateTimeValue;
public DateTimePicker() {
FXMLLoader loader = new FXMLLoader(this.getClass().getResource(
ScreenPaths.DATE_TIME_PICKER));
loader.setController(this);
loader.setRoot(this);
try {
loader.load();
} catch (IOException e) {
}
}
@FXML
private void initialize() {
showTimePickerBtn.setOnAction(event -> this.showTimePicker());
hourField = new NumberPicker();
hourField.setBounds(0, 23);
hourField.setWrapAround(true);
minuteField = new NumberPicker();
minuteField.setBounds(0, 59);
minuteField.setWrapAround(true);
currentLocalDateTimeValue = new SimpleObjectProperty<>();
datePicker.valueProperty().addListener((ObservableValue<? extends LocalDate> observable,
LocalDate oldValue, LocalDate newValue) -> {
LocalDateTime newLDT;
if (newValue != null) {
newLDT = LocalDateTime.of(newValue.getYear(),
newValue.getMonth(), newValue.getDayOfMonth(),
hourField.getValue(), minuteField.getValue());
currentLocalDateTimeValue.set(newLDT);
} else {
currentLocalDateTimeValue.set(null);
}
});
hourField.valueProperty().addListener((ObservableValue<? extends Number> observable,
Number oldValue, Number newValue) -> {
if (currentLocalDateTimeValue.getValue() != null) {
LocalDateTime newLDT = LocalDateTime.of(currentLocalDateTimeValue.getValue().getYear(),
currentLocalDateTimeValue.getValue().getMonth(), currentLocalDateTimeValue.getValue().getDayOfMonth(),
hourField.getValue(), minuteField.getValue());
currentLocalDateTimeValue.set(newLDT);
} else {
currentLocalDateTimeValue.set(null);
}
});
minuteField.valueProperty().addListener((ObservableValue<? extends Number> observable,
Number oldValue, Number newValue) -> {
if (currentLocalDateTimeValue.getValue() != null) {
LocalDateTime newLDT = LocalDateTime.of(currentLocalDateTimeValue.getValue().getYear(),
currentLocalDateTimeValue.getValue().getMonth(), currentLocalDateTimeValue.getValue().getDayOfMonth(),
hourField.getValue(), minuteField.getValue());
currentLocalDateTimeValue.set(newLDT);
} else {
currentLocalDateTimeValue.set(null);
}
});
}
/**
* Manually set a LocalDateTime value for this control.
*
* @param val The {@link LocalDateTime} value for this control.
*/
public void setValue(LocalDateTime val) {
if (val == null) {
return;
}
LocalDate day = LocalDate.of(val.getYear(), val.getMonthValue(),
val.getDayOfMonth());
datePicker.setValue(day);
hourField.setValue(val.getHour());
minuteField.setValue(val.getMinute());
}
/**
* Returns the currently set LocalDateTime.
*
* @return the {@link LocalDateTime} value of this control.
*/
public LocalDateTime getValue() {
return currentLocalDateTimeValue.getValue();
}
/**
* Returns the Observable property of the DateTimePicker's current
* LocalDateTime value.
*
* @return the Observable property of the DateTimePicker's current
* LocalDateTime value.
*/
public ObjectProperty<LocalDateTime> valueProperty() {
return currentLocalDateTimeValue;
}
/**
* This is triggered when the user wants to view the screen for setting a
* certain time for their LocalDateTime.
*/
public void showTimePicker() {
HBox topContainer = new HBox();
topContainer.getChildren().addAll(hourField, new Label(":"),
minuteField);
topContainer.setSpacing(3);
DialogPopup.showNodeApplicationlModal(topContainer);
}
}
答案 0 :(得分:1)
通常,可编辑单元格在处于非编辑模式时会显示默认文本,而在编辑模式下则会显示编辑控件(DateTimePicker
)。您的自定义单元格实现需要处理它们之间的转换,以及确保在更新单元格项目时正确更新编辑控件的文本和值。
因此,如果处于编辑模式(updateItem(...)
),则应覆盖DateTimePicker
以更新isEditing()
的值,如果不是,则覆盖文本。覆盖startEdit()
切换为显示DateTimePicker
而不是文字,并cancelEdit()
切换回来。
您可能根本不需要覆盖commitEdit()
。如果您的列绑定到某个属性,则默认的commitEdit()
应该更新该属性(或者您可以在向该列注册的onEditCommit
处理程序中执行此操作)。
tutorial有一个完全实现的可编辑表格单元格的示例:请参见底部附近的清单13.11。
但是,您需要在适当的时候调用commitEdit(...)
。这样做的语义有点棘手:如果用户在DateTimePicker
内的任何单个控件都有焦点时按下Enter键,并且焦点可能远离{{1}时,您可能想要提交编辑完全。
我建议您在DateTimePicker
课程中创建onAction
媒体资源。这很容易做到,您只需在属性更改时调用DateTimePicker
。在Richard Bair's MoneyField中有一个很好的例子(该链接中有很多内容,只要看看他创建setEventHander(...)
处理程序的位置)。然后,您可以(在onAction
内部)检查各个控件上的操作事件(或者可能是Enter键按下),并在发生这种情况时调用DateTimePicker
。然后,您的表格单元格实现可以使用fireEvent(new ActionEvent(...))
注册onAction
并调用DateTimePicker
。
对焦点损失进行编辑不应该困难得多。可能会在commitEdit(...)
中公开ReadOnlyBooleanProperty hasFocus()
:
DateTimePicker
然后,您的单元格实现可以观察该属性,并在其变为private final ReadOnlyBooleanWrapper hasFocus = new ReadOnlyBooleanWrapper(this, "hasFocus");
hasFocus.bind(
hourField.focusedProperty()
.or(minuteField.focusedProperty())
.or(datePicker.focusedProperty())
.or(showTimePickerButton.focusedProperty()));
// ...
public ReadOnlyBooleanProperty hasFocusProperty() {
return hasFocus.getReadOnlyProperty();
}
时提交编辑。您可能需要进行一些试验才能使其正常工作。