JavaFX Control TreeTableView

El control TreeTableView combina las características de los controles TreeView y TableView, el mismo muestra un TreeView dentro de un TableView, lo que hace de este control una poderosa herramienta para mostrar datos organizados de manera jerárquica.

TreeTableView ttv = new TreeTableView();

StackPane root = new StackPane();
root.getChildren().add(ttv);
root.setPadding(new Insets(10.0));

Scene scene = new Scene(root, 480, 320);

primaryStage.setTitle("JavaFX :: TreeTableView");
primaryStage.setScene(scene);
primaryStage.show();

Con esto creamos un TreeTableView vacío, usamos la clase del mismo nombre para hacerlo y lo agregamos al Scene y luego este a nuestro Stage, si lo mostramos veremos lo siguiente:

image

Para crear una columna de datos usaremos la clase TreeTableColumn crearemos una columna para cada miembro de la clase Empleado, agregamos las columnas usando el método getColumns().addAll(…) donde indicamos todas las columnas que deseamos añadir.

TreeTableColumn<Empleado, String> ttcNombre = new TreeTableColumn<>("Nombre");
TreeTableColumn<Empleado, String> ttcApellido = new TreeTableColumn<>("Apellido");
TreeTableColumn<Empleado, LocalDate> ttcNacimiento = new TreeTableColumn<>("Fecha de Nacimiento");
TreeTableColumn<Empleado, Double> ttcSalario = new TreeTableColumn<>("Salario Bruto");

ttv.getColumns().addAll(ttcNombre, ttcApellido, ttcNacimiento, ttcSalario);

image

Debemos agregar los datos del mismo modo que lo hicimos con el TreeView en el tutorial anterior, primero creamos un elemento raíz, luego a este le agregamos sus hijos, para mayor información ver el tutorial correspondiente.

Empleado emp1 = new Empleado("Juan", "Perez", LocalDate.parse("2000-05-01"), 500.0);
Empleado emp11 = new Empleado("Maria", "Lopez", LocalDate.parse("2010-05-01"), 400.0);
Empleado emp12 = new Empleado("Ivania", "Gonzalez", LocalDate.parse("2010-08-07"), 300.0);

TreeItem<Empleado> itm1 = new TreeItem<>(emp1);
TreeItem<Empleado> itm11 = new TreeItem<>(emp11);
TreeItem<Empleado> itm12 = new TreeItem<>(emp12);

itm1.getChildren().addAll(itm11, itm12);

ttv.setRoot(itm1);

El elemento itm1 es la raíz, a este le añadimos los elementos itm11 y itm12, estos elementos son TreeItem<Empleado> usados para representar a un empleado, mediante setRoot(itm1) le indicamos al TreeTableView cual es el elemento raíz.

image

Este ejemplo quizá no sea el más adecuado para comprender la funcionalidad de este control, pero nos sirve para aprender a utilizarlo, veamos un ejemplo mas práctico y realista.

Explorador de Archivos Avanzados

Vamos a mejorar el explorador de archivos que creamos en el tutorial TreeView,  lo que haremos será utilizar un TreeTableView para mostrar el archivo e información más detallada del mismo.

image

Lo primero que haremos será cambiar el control y agregar las tres columnas correspondientes, para las columnas tamaño y fecha modificamos el cellValueFactory para que muestre el tamaño de archivo y la ultima fecha de modificación.

TreeTableColumn<File, FileOrDir> ttcNombre = new TreeTableColumn<>("Nombre");
TreeTableColumn<File, String> ttcTamano = new TreeTableColumn<>("Tamaño");
TreeTableColumn<File, Date> ttcFecha = new TreeTableColumn<>("Fecha de Modificación");

ttcTamano.setCellValueFactory(cell -> {
    File file = cell.getValue().getValue();
    return new SimpleStringProperty(getFileSize(file));
});

ttcFecha.setCellValueFactory(cell -> {
    File file = cell.getValue().getValue();
    return new SimpleObjectProperty(new Date(file.lastModified()));
});

TreeTableView<File> treeView = new TreeTableView<>();
treeView.setShowRoot(false);
treeView.setRoot(archivos);
treeView.getColumns().addAll(ttcNombre, ttcTamano, ttcFecha);

Para la columna nombre modificaremos el cellFactory y cellValueFactory, el primero porque deseamos mostrar un icono diferente si se trata de un archivo o una carpeta, el segundo extraemos el nombre y  un booleano que nos indica si se trata de un archivo.

ttcNombre.setCellValueFactory(value -> {
    File file = value.getValue().getValue();
    FileOrDir fod = new FileOrDir(file.toString(), file.isFile());
    return new ReadOnlyObjectWrapper(fod);
});

ttcNombre.setCellFactory(cell -> {
    return new TreeTableCell<File, FileOrDir>() {

        @Override
        protected void updateItem(FileOrDir item, boolean empty) {
            super.updateItem(item, empty);

            if (empty) {
                this.setGraphic(null);
                this.setText(null);
            } else {
                this.setGraphic(new OctIconView(item.isFile ? OctIcon.FILE : OctIcon.FILE_DIRECTORY));
                this.setText(item.name);
            }
        }

    };
});

De momento lo dejamos aquí, seguiremos viendo mas características de este y otros controles JavaFX en próximos tutoriales.

Proyecto GitHub: Explorador Archivos JavaFX

Comentarios

  1. Cómo puedo agregar un checkbox en una 4ta columna, el cual sólo sea visible si la fila contiene un archivo, no un directorio.

    ResponderEliminar
  2. Lo primero seria crear una columna de tipo TreeTableColumn luego usar setCellFactory() para definir el contenido de la celda, parecido a como se hace e el último fragmento de código del tutorial, salvo que en lugar de añadir un icono crearías un CheckBox el cual cambiarías se estado según te lo indique la variable item.

    ResponderEliminar

Publicar un comentario

Temas relacionados

Entradas populares de este blog

tkinter Grid

Histogramas OpenCV Python

Modelo de Iluminación Phong - Tutorial OpenGL

tkinter Canvas