JavaFx TableView 单元格失去焦点后自动提交数据

75 阅读1分钟
/**

 * 失去焦点时自动提交数据,无论是否点击表格哪里
 */

public class FocusLostTextFieldTableCell<S, T> extends TableCell<S, T> {

    private TextField textField;

    private final StringConverter<T> converter;

    public FocusLostTextFieldTableCell(StringConverter<T> converter) {
        this.converter = converter;
    }

    public static <S> Callback<TableColumn<S, String>, TableCell<S, String>> forTableColumn() {
        return forTableColumn(new DefaultStringConverter());
    }

    public static <S, T> Callback<TableColumn<S, T>, TableCell<S, T>> forTableColumn(StringConverter<T> converter) {
        return param -> new FocusLostTextFieldTableCell<>(converter);
    }
    ```
@Override
public void startEdit() {
    if (!isEditable() || !getTableView().isEditable() || !getTableColumn().isEditable()) {
        return;
    }
    super.startEdit();
    if (textField == null) {
        createTextField();
    }
    setText(null);
    setGraphic(textField);
    textField.selectAll();
    textField.requestFocus();
}

@Override
public void cancelEdit() {
    super.cancelEdit();
    setText(converter.toString(getItem()));
    setGraphic(null);
}

@Override
public void updateItem(T item, boolean empty) {
    super.updateItem(item, empty);
    if (empty) {
        setText(null);
        setGraphic(null);
    } else {
        if (isEditing()) {
            if (textField != null) {
                textField.setText(converter.toString(getItem()));
            }
            setText(null);
            setGraphic(textField);
        } else {
            setText(converter.toString(getItem()));
            setGraphic(null);
        }
    }
}```
private void createTextField() {
    textField = new TextField(converter.toString(getItem()));
    textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
    textField.setOnAction(event -> commitEdit(converter.fromString(textField.getText())));
    textField.setOnKeyPressed(event -> {
        if (event.getCode() == KeyCode.ESCAPE) {
            cancelEdit();
        }
    });
    // 关键点:监听焦点丢失事件
    textField.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
        if (!isNowFocused) {
            System.out.println("单元格失去焦点" + !isNowFocused);
            commitEdit(converter.fromString(textField.getText()));
        }
    });
}```
@Override
public void commitEdit(T newValue) {
    // 如果仍在编辑状态,调用父类正常提交
    if (isEditing()) {
        super.commitEdit(newValue);
    } else if (!newValue.equals(getItem())) {
        // 如果已退出编辑状态,手动触发提交事件
        TableColumn<S, T> column = getTableColumn();
        if (column != null) {
            // 创建并触发编辑提交事件
            TableColumn.CellEditEvent<S, T> event = new TableColumn.CellEditEvent<>(getTableView(), new TablePosition<>(getTableView(), getIndex(), column), TableColumn.editCommitEvent(), newValue);
            Event.fireEvent(column, event);
        }
    }
    // 无论是否编辑状态,更新显示
    setText(converter.toString(newValue));
    setGraphic(null);
}