Social

jueves, 25 de abril de 2013

JavaFX: Tabla Editable


Dentro de las capacidades de las tablas de JavaFX esta la posibilidad de crear celdas personalizadas con otros elementos visuales. En este caso usamos un TextField para permitir crear el efecto de una tabla editable. 


Para entender el código es recomendable haber leido el post que se indica al principio. Ya que se usa una lista de objetos base para llegar la tabla, se necesita definir en este objeto. En este caso es el mismo de la entrada anterior.


public static class Person {
private final SimpleStringProperty firstName;
private final SimpleStringProperty lastName;
private final SimpleStringProperty phone;
private Person(String first, String last, String phon) {
this.firstName = new SimpleStringProperty(first);
this.lastName = new SimpleStringProperty(last);
this.phone = new SimpleStringProperty(phon);
}
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String first) {
firstName.set(first);
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String last) {
lastName.set(last);
}
public String getPhone() {
return phone.get();
}
public void setEmail(String phone) {
this.phone.set(phone);
}
}
Para lograr editar la tabla, se necesita crear un nuevo tipo de celda. En este caso se crea la clase EditingCell que hereda de la celda. Luego se sobrescriben los métodos. El método start inicia la edición y si la celda es nula inicializa el TextField con el método createTextField() con un listener para detectar las teclas Enter y Esc. Luego el método cancel simplemente llama al de la clase superior y maneja el TextField. El método uptate también llama al de la clase superior y actualiza la visualización de la celda mostrando el TextField o no cuando se esta editando. El ultimo método simplemente devuelve el contenido de la celda.

public static class EditingCell extends TableCell<Person, String> {
private TextField textField;
public EditingCell() {
}
@Override
public void startEdit() {
super.startEdit();
if (textField == null) {
createTextField();
}
setText(null);
setGraphic(textField);
textField.selectAll();
}
@Override
public void cancelEdit() {
super.cancelEdit();
setText((String) getItem());
setGraphic(null);
}
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
if (textField != null) {
textField.setText(getString());
}
setText(null);
setGraphic(textField);
} else {
setText(getString());
setGraphic(null);
}
}
}
private void createTextField() {
textField = new TextField(getString());
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
textField.setOnKeyReleased(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent t) {
if (t.getCode() == KeyCode.ENTER) {
commitEdit(textField.getText());
} else if (t.getCode() == KeyCode.ESCAPE) {
cancelEdit();
}
}
});
}
private String getString() {
return getItem() == null ? "" : getItem().toString();
}
}
Finalmente le asignamos a la columna deseada una función de retorno o callback. En este caso se le asigna solamente a la columna Teléfono.

//Definimos un callback que nos devolvera la clase EditingCell
//EditingCell devuleve un TextField con el cual se puede hacer la edición
Callback<TableColumn, TableCell> cellFactory = new Callback<TableColumn, TableCell>() {
public TableCell call(TableColumn p) {
return new EditingCell();
}
};
//Se puede agregar el callback a las columnas que se desee
//En este caso se agregará a la de telefono.
TableColumn firstNameCol = new TableColumn("Primer Nombre");
firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
firstNameCol.setMinWidth(140);
TableColumn lastNameCol = new TableColumn("Segundo Nombre");
lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
lastNameCol.setMinWidth(140);
TableColumn phoneCol = new TableColumn("Teléfono");
phoneCol.setCellValueFactory(new PropertyValueFactory<Person, String>("phone"));
phoneCol.setCellFactory(cellFactory); //le agregamos al call back a la columna.
phoneCol.setMinWidth(100);
table.setItems(data);
table.getColumns().addAll(firstNameCol, lastNameCol, phoneCol);

No hay comentarios :

Publicar un comentario