I have a table cell factory responsible for creating an editable cell in a JavaFX TableView.
I\'m trying to implement some added functionality to the tableview so th
I created my own workaround (but for JavaFX 2). Main idea - transform cancelEdit() to commitEdit(). With possible validation of committed text via validator.
/** Validator. */
public interface TextColumnValidator {
boolean valid(T rowVal, String newVal);
}
/**
* Special table text field cell that commit its content on focus lost.
*/
public class TextFieldTableCellEx extends TextFieldTableCell {
/** */
private final TextColumnValidator validator;
/** */
private boolean cancelling;
/** */
private boolean hardCancel;
/** */
private String curTxt = "";
/** Create cell factory. */
public static Callback, TableCell>
cellFactory(final TextColumnValidator validator) {
return new Callback, TableCell>() {
@Override public TableCell call(TableColumn col) {
return new TextFieldTableCellEx<>(validator);
}
};
}
/**
* Text field cell constructor.
*
* @param validator Input text validator.
*/
private TextFieldTableCellEx(TextColumnValidator validator) {
this.validator = validator;
}
/** {@inheritDoc} */
@Override public void startEdit() {
super.startEdit();
curTxt = "";
hardCancel = false;
Node g = getGraphic();
if (g != null) {
final TextField tf = (TextField)g;
tf.textProperty().addListener(new ChangeListener() {
@Override public void changed(ObservableValue extends String> val, String oldVal, String newVal) {
curTxt = newVal;
}
});
tf.setOnKeyReleased(new EventHandler() {
@Override public void handle(KeyEvent evt) {
if (KeyCode.ENTER == evt.getCode())
cancelEdit();
else if (KeyCode.ESCAPE == evt.getCode()) {
hardCancel = true;
cancelEdit();
}
}
});
// Special hack for editable TextFieldTableCell.
// Cancel edit when focus lost from text field, but do not cancel if focus lost to VirtualFlow.
tf.focusedProperty().addListener(new ChangeListener() {
@Override public void changed(ObservableValue extends Boolean> val, Boolean oldVal, Boolean newVal) {
Node fo = getScene().getFocusOwner();
if (!newVal) {
if (fo instanceof VirtualFlow) {
if (fo.getParent().getParent() != getTableView())
cancelEdit();
}
else
cancelEdit();
}
}
});
Platform.runLater(new Runnable() {
@Override public void run() {
tf.requestFocus();
}
});
}
}
/** {@inheritDoc} */
@Override public void cancelEdit() {
if (cancelling)
super.cancelEdit();
else
try {
cancelling = true;
if (hardCancel || curTxt.trim().isEmpty())
super.cancelEdit();
else if (validator.valid(getTableView().getSelectionModel().getSelectedItem(), curTxt))
commitEdit(curTxt);
else
super.cancelEdit();
}
finally {
cancelling = false;
}
}
}
Update: this code was written as a part of Apache Ignite Schema Import GUI Utility. See full version of TableCell code: https://github.com/apache/ignite/blob/ignite-1.9/modules/schema-import/src/main/java/org/apache/ignite/schema/ui/Controls.java
Also you could build this utility (it is a very simple utility with 2 screens) and play with it under Java7/javaFx2 & Java8/JavaFx8.
I tested - it works under both of them.