TableView Editable (JavaFX)

Seguimos viendo más posibilidades del control JavaFX TableView, esta vez veremos cómo editar los datos que son mostrados en el control y veremos cómo personalizar el control usado para la edición de las celdas, por ejemplo: para editar un dato tipo fecha usaremos un control para el manejo de fechas DatePicker, del mismo modo para los demás datos usaremos el control correspondiente.

Para hacer el TableView editable usaremos el método table_view.setEditable(true), para controlar la edición el TableColumn soporta tres eventos: onEditStart, onEditCommit, onEditCancel, el primero el lanzado cuando la celda cambia al modo edición, el segundo al confirmar la edición, por ejemplo al presionar la tecla ENTER, y el último al cancelar la edición por ejemplo al presionar la tecla ESC.

Editar TableView con TextField


Las columnas de un TableView que presentan información de tipo String pueden ser editadas usando TextFieldTableCell esta clase genera un control TextField que permite editar el texto que contiene una celda, lo habilitamos haciendo doble clic sobre la celda, el método estático TextFieldTableCell.forTableColumn() crea la celda editable.

TableColumn<Persona, String> tc_nombre = new TableColumn<>("Nombre");
tc_nombre.setCellValueFactory(new PropertyValueFactory<Persona, String>("Nombre"));
tc_nombre.setCellFactory(TextFieldTableCell.forTableColumn());

textfiled tableview
Como lo mencionamos anteriormente tenemos tres eventos disponibles para responder a las acciones de edición, para este ejemplo veremos el evento OnEditCommit producido al aceptar la edición, los demás eventos funcionan de manera similar, usaremos los métodos getNewValue() y getOldValue() para obtener el valore nuevo y el anterior a la edición, el método getRowValue() nos devuelve el objeto que representa la fila.

tc_nombre.setOnEditCommit(data -> {
    System.out.println("Nuevo Nombre: " +  data.getNewValue());
    System.out.println("Antiguo Nombre: " + data.getOldValue());

    Persona p = data.getRowValue();
    p.setNombre(data.getNewValue());

    System.out.println(p);
});

Aprovechamos este evento para guardar los nuevos datos, si tuviésemos una base de datos podríamos guardar estos nuevos cambios.

Algunas veces necesitamos mostrar y editar datos que no son de tipo String, por ejemplo una fecha aunque se puede mostrar y editar como texto es un objeto LocalDate por ello requerimos un convertidor de String a LocalDate y viceversa, la clase StringConverter nos permite crear estos convertidores, LocalDateStringConverter nos sirve a nuestros propósitos.

TableColumn<Persona, LocalDate> tc_nacimiento = new TableColumn<>("Fecha de Nacimiento");
tc_nacimiento.setCellValueFactory(new PropertyValueFactory<Persona, LocalDate>("nacimiento"));
LocalDateStringConverter converter = new LocalDateStringConverter();
tc_nacimiento.setCellFactory(TextFieldTableCell.<Persona, LocalDate>forTableColumn(converter));
tc_nacimiento.setOnEditCommit(data -> { data.getRowValue().setNacimiento(data.getNewValue()); });

Editar TableView con Choice Box


Al activar la edición de una celda con este control el mismo despliega una lista de elementos seleccionables, para este tutorial lo usaremos para mostrar la lista de posibles géneros de una persona, el usuario selecciona el que más le parezca, en ese momento se produce el evento onEditCommit.

Esta celda editable la creamos usando el método estático forTableColumn() debemos indicarle cuales son los elementos a mostrar, pertenece a la clase ChoiceBoxTableCell.

TableColumn<Persona, Persona.Genero> tc_genero = new TableColumn<>("Genero");
tc_genero.setCellValueFactory(new PropertyValueFactory<Persona, Persona.Genero>("Genero"));
tc_genero.setCellFactory(ChoiceBoxTableCell
        .forTableColumn(Persona.Genero.MASCULINO, Persona.Genero.FEMENINO));

choice box tableview

Editar TableView con Check Box


Un Check Box es un control que normalmente nos permite representar dos estados, habilitado y deshabilitado, por ello es común usarlo para representar datos de tipo Boolean lo creamos con el método forTableColumn() de la clase CheckBoxTableCell debemos indicarle a que columna pertenece.

TableColumn<Persona, Boolean> tc_activo = new TableColumn<>("Activo");
tc_activo.setCellValueFactory(cell -> {
    Persona p = cell.getValue();
    return new ReadOnlyBooleanWrapper(p.getActivo());
});
tc_activo.setCellFactory(CheckBoxTableCell.forTableColumn(tc_activo));

check box tableview
Este control no produce ninguno de los tres eventos de edición antes mencionados.

Si usamos propiedades JavaFX el control de edición de la celda se enlaza con la propiedad y cambia automáticamente su valor cuando este es editado, como ejemplo cambiaremos la propiedad activo para usar propiedades JavaFX, la modificación en la clase Persona es la siguiente:

private BooleanProperty _activo;

public final BooleanProperty activoProperty() { return this._activo; }

public final Boolean getActivo() { return _activo.get(); }

public final void setActivo(Boolean activo) { this._activo.set(activo); }

Al crear la columna editable lo hacemos del siguiente modo:

TableColumn<Persona, Boolean> tc_activo = new TableColumn<>("Activo");
tc_activo.setCellValueFactory(cell -> cell.getValue().activoProperty());
tc_activo.setCellFactory(CheckBoxTableCell.forTableColumn(tc_activo));

Usando propiedades se aprovechan todas las capacidades de los controles JavaFX, por lo que recomiendo siempre utilizarlas, sin embargo también tengamos en cuanta que podemos usar clases con propiedades JavaBeans.

GitHub: Edición de TableView JavaFX

Comentarios

Entradas populares de este blog

Conectar SQL Server con Java

Entrenar OpenCV en Detección de Objetos

Acceso a la webcam con OpenCV

JavaFx 8 Administrar ventanas

Analizador Léxico