gpt4 book ai didi

JavaFX 自定义 TableCell 监听

转载 作者:行者123 更新时间:2023-12-01 12:34:52 26 4
gpt4 key购买 nike

例如,当您按下 Enter 键时,TextFieldTableCell 会响应并调用 commitEdit()。

如果我使用自定义节点来显示,那么我如何监听确认编辑的方法?例如,我有一个 DateTimePicker,它扩展了 VBox。我无法将 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();
}

}

日期时间选择器:

/**
* 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);
}

}

最佳答案

通常,可编辑单元格在非编辑模式下将显示默认文本,在编辑模式下将显示编辑控件(您的 DateTimePicker )。您的自定义单元实现需要处理这些之间的转换,并确保在更新单元格的项目时正确更新编辑控件的文本和值。

所以你应该覆盖updateItem(...)更新 DateTimePicker 的值如果处于编辑模式 ( isEditing() ) 或文本(如果不处于编辑模式)。覆盖startEdit()切换显示 DateTimePicker而不是文本,和 cancelEdit()切换回来。

您可能不需要覆盖 commitEdit()根本不。如果您的列绑定(bind)到属性,则默认 commitEdit()应该更新该属性(或者您可以在向列注册的 onEditCommit 处理程序中执行此操作)。

tutorial有一个完全实现的可编辑表格单元的示例:请参阅底部附近的 list 13.11。

但是,您需要调用 commitEdit(...)在适当的时间。这个语义有点棘手:如果用户在 DateTimePicker 中的任何单个控件时按 Enter 键,您可能想要提交编辑。有焦点,也许当焦点从 DateTimePicker 移开时完全。

我建议创建一个 onAction您的属性(property)DateTimePicker类(class)。这很容易做到,你只需调用 setEventHander(...)当属性发生变化时。 Richard Bair's MoneyField中有一个很好的例子(该链接中有很多内容,只需看看他在哪里创建 onAction 处理程序)。然后,您可以(在 DateTimePicker 内部)检查各个控件上的操作事件(或者可能是 Enter 键按下)并调用 fireEvent(new ActionEvent(...))当这种情况发生时。然后您的表格单元实现可以注册 onActionDateTimePicker并调用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();
}

然后,您的单元实现可以观察该属性,并在其更改为 false 时提交编辑。 。您可能需要进行一些尝试才能使其令人满意地工作。

关于JavaFX 自定义 TableCell 监听,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25678242/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com