Buscar elemento en un TableView JavaFX

Previamente hemos estudiado el control TableView de JavaFX por lo que en este tutorial desarrollaremos una pequeña aplicación para demostrar cómo podemos programar un cuadro de búsquedas para ubicar rápidamente un elemento que se encuentre dentro de este control, para esto utilizaremos una colección de tipo FilteredList<T>.

Lo primero que haremos será definir nuestra GUI mediante código JavaFX.

TableView<Person> tableView = new TableView<>();
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);

TableColumn<Person, String> tcNombre = new TableColumn<>("Nombre");
tcNombre.setCellValueFactory(c -> c.getValue().firstNameProperty());

TableColumn<Person, String> tcApellido = new TableColumn<>("Apellido");
tcApellido.setCellValueFactory(c -> c.getValue().lastNameProperty());

TableColumn<Person, Number> tcEdad = new TableColumn<>("Edad");
tcEdad.setCellValueFactory(c -> c.getValue().ageProperty());

tableView.getColumns().add(tcNombre);
tableView.getColumns().add(tcApellido);
tableView.getColumns().add(tcEdad);
tableView.setItems(createPersonList());

TextField search = new TextField();
search.setPromptText("Buscar...");
HBox.setHgrow(search, Priority.ALWAYS);

HBox searchBar = new HBox();
searchBar.getChildren().add(search);

VBox root = new VBox();
root.setSpacing(5.0);
root.setPadding(new Insets(10.0));
root.getChildren().addAll(searchBar, tableView);

Scene scene = new Scene(root, 800, 600);

primaryStage.setTitle("JavaFX Buscar en TableView");
primaryStage.setScene(scene);
primaryStage.show();

Este código produce el siguiente resultado:

Buscar elemento en TableView JavaFX

FilteredList

Para que el TableView<T> pueda filtrar sus elementos debemos proporcionarle un FilteredList<T> en lugar del ObservableList<T>, creamos fácilmente el primero a partir del segundo de la siguiente manera:

FilteredList<Person> filteredData = new FilteredList<>(createPersonList(), p -> true);
tableView.setItems(filteredData);

El predicate p -> true establece que inicialmente deseamos mostrar todos los elementos de la lista.

El siguiente paso es detectar los cambios en el TextField, cuando se escriba un nuevo texto aplicaremos un filtro basado en el mismo, por ejemplo, para filtrar los nombres que contengan el texto escrito por el usuario.

TextField search = new TextField();
search.setPromptText("Buscar...");
search.textProperty().addListener((prop, old, text) -> {
    filteredData.setPredicate(person -> {
        if(text == null || text.isEmpty()) return true;
        
        String name = person.getFirstName().toLowerCase();  
        return name.contains(text.toLowerCase());
    });
});

El método setPredicate() define el filtro de búsqueda, el objeto person define el elemento actual que estamos evaluando, verificamos si el primer nombre contiene el texto escrito en el cuadro de búsqueda, convertirnos ambos textos a minúsculas.

Cuadro de búsqueda para un TableView JavaFX

Si lo deseamos también podemos buscar por edad, por ejemplo aquellas personas mayores de 20 años, otra opción es buscar por apellido y utilizar los métodos de la clase String como: startsWith() para ubicar los apellidos que inicien con la palabra escrita o incluso usar una expresión regular para hacer coincidir patrones más complejos.

Para finalizar debo mencionar que al utilizar un FilteredList<T> la ordenación en el TableView<T> se deshabilita, al hacer clic sobre la cabecera de la columna esta no se ordenará, para activarlo haremos lo siguiente:

FilteredList<Person> filteredData = new FilteredList<>(createPersonList(), p -> true);

SortedList<Person> sortedData = new SortedList<>(filteredData);
sortedData.comparatorProperty().bind(tableView.comparatorProperty());

tableView.setItems(sortedData);

Con esto encapsulamos la lista dentro de un objeto SortedList<T> que representa una lista ordenada de elementos, luego enlazamos las propiedades comparatorProperty() del TableView<T> y este objeto, así activamos la característica de ordenación.

Descargar código: JavaFX Buscar en TableView.zip

Comentarios

  1. Hola!

    Estoy intentando hacer un ComboBox que está compuesto por los valores de un campo ENUM de la base de datos ("alta", "media", "baja"). De modo que cuando seleccione uno u otro cargue solo los registros con ese filtro.

    ¿Se te ocurre cómo hacerlo?

    Gracias

    ResponderEliminar
    Respuestas
    1. La idea base es la misma que se presenta en este ejemplo, salvo que debes cambiar el filtro, en lugar de filtrar por el texto ingresado deberas hacerlo por el elemento seleccionado en el ComboBox, todo lo demás queda igual.

      Eliminar
  2. Gracias, lo integre en el código de mi aplicación y funciona de maravilla

    ResponderEliminar

Publicar un comentario

Temas relacionados

Entradas populares de este blog

tkinter Grid

Controles y Contenedores JavaFX 8 - I

Conectar SQL Server con Java

Histogramas OpenCV Python