En algunos foros he visto que constantemente la gente pregunta como pueden filtrar los resultados de una consulta mostrada en un JTable al escribir en un JTextField. Esto es algo muy Ăştil en aplicaciones donde se desee realizar una bĂşsqueda de cualquier cosa; por ejemplo en una aplicaciĂłn de punto de venta donde se desee buscar algĂşn producto, en una librerĂa para buscar algĂşn libro, en una aplicaciĂłn para el registro de notas acadĂ©micas donde se deseen buscar datos de estudiantes, etc.
Antes de empezar este tutorial, primero se deben tener en cuenta algunas consideraciones:
- Este proceso se realiza de igual forma para datos estáticos en un JTable, o para resultados que son producto de una consulta a una base de datos.
- Para realizar el filtrado de los resultados, los datos deben estar de antemano en la Tabla, es decir, ya debe estar creado el modelo del JTable. Además si no se hiciera asĂ, imagina que pasarĂa si se hiciera por ejemplo una consulta a una tabla de una base de datos que tiene un millĂłn de registros; cada vez que digitemos una letra, habrĂa que hacer la consulta a todo el millĂłn de registros, lo cual en cualquier momento saturará el servidor de la base de datos.
En este caso, haremos una tabla que llenaremos nosotros mismos con algunos datos de personas como su identificaciĂłn, nombre y profesiĂłn, pero como lo dije anteriormente, funciona de igual manera para datos recogidos desde una consulta a una base de datos (La consulta debe hacerse primero, por ejemplo podrĂa hacerse en el constructor de la clase).
¿QuĂ© Usaremos Para Este Tutorial?
- NetBeans v7.4
- Java 1.7
Nivel: Intermedio
Tiempo: 20 minutos
1. Creamos un proyecto en NetBeans con la siguiente estructura:
2. Creamos la interfaz de usuario la cual comprende un JFrame donde hemos agregado 3 JRadioButtons con su respectivo ButtonGroup, un JLabel, un JTextField y un JTable.
3. Creamos el modelo del JTable y sus respectivos datos. Para esto crearemos un método para el modelo y otro para llenar la tabla con datos:
private DefaultTableModel tabladatos; public final void setModeloTabla() { // Inicializamos el modelo de la tabla tabladatos = new DefaultTableModel(); // Creamos los tĂtulos de la tabla y los insertamos en el modelo String[] titulostabla = {"IdentificaciĂłn","Nombre","ProfesiĂłn"}; tabladatos.setColumnIdentifiers(titulostabla); // Insertamos el modelo creado en el JTable this.jTdatos.setModel(tabladatos); } public void cargarDatos() { // Creamos una matriz con los datos que llenarán la tabla Object[][] datos = { {98735671,"Felipe Gomez","Arquitecto"}, {56319046,"Sandra Rios","Docente"}, {11653215,"Camilo Rodriguez","Ingeniero"}, {83211674,"Maria Lopez","Oficial de Policia"}, {76325901,"David Ospina","Docente"}, {90119740,"Hector Cortes","Ingeniero"}, {65267938,"Laura Martinez","Docente"}, {10941507,"El Javatar","Ingeniero"}, {30297534,"Camila Salas","Oficial de Policia"}, {28016745,"Pedro Fernandez","Arquitecto"}, }; // Recorremos las filas de la matriz para ir llenando la tabla for (Object[] dato : datos) { tabladatos.addRow(dato); } }
4. Añadimos éstos dos métodos al constructor de la clase:
De esta forma si quisieramos llenar la tabla con datos provenientes de una consulta a una base de datos, solo cambiarĂamos el cĂłdigo que va dentro del mĂ©todo cargarDatos().
Si ejecutáramos nuestro proyecto en Ă©ste momento, se verĂa de la siguiente forma:
Ahora solo nos resta crear el método encargado de realizar el filtro y adjuntarlo a un evento del JTextField, pero vamos por partes.
5. Creamos el método encargado de realizar el filtro:
6. Ahora lo que haremos es añadirle un evento de tipo KeyTyped al JTextField, el cual a su vez tendrá un KeyListener que a su vez estará escuchando las acciones emitidas dentro de otro evento KeyTyped. Éste último evento será el que llamará al método filtro():
El cĂłdigo completo (omitiendo algunas partes del cĂłdigo generado por NetBeans) quedarĂa de la siguiente forma:
Ejecutamos el proyecto y listo. Próximamente estaré publicando el video donde muestro paso a paso la realización de este proyecto.
public Interfaz() { initComponents(); setModeloTabla(); cargarDatos(); }
De esta forma si quisieramos llenar la tabla con datos provenientes de una consulta a una base de datos, solo cambiarĂamos el cĂłdigo que va dentro del mĂ©todo cargarDatos().
Si ejecutáramos nuestro proyecto en Ă©ste momento, se verĂa de la siguiente forma:
5. Creamos el método encargado de realizar el filtro:
public void filtro() { //Obtenemos el valor del JTextField para el filtro String filtro = jTFfiltrar.getText(); // Identificamos cual es el JRadioButton seleccionado para filtrar el // resultado de acuerdo a los datos de la columna elegida if (jRBident.isSelected()) { int columna = 0; trsfiltro.setRowFilter(RowFilter.regexFilter(filtro, columna)); } else if (jRBnombre.isSelected()) { int columna = 1; trsfiltro.setRowFilter(RowFilter.regexFilter(filtro, columna)); } else if (jRBprofesion.isSelected()) { int columna = 2; trsfiltro.setRowFilter(RowFilter.regexFilter(filtro, columna)); } }
6. Ahora lo que haremos es añadirle un evento de tipo KeyTyped al JTextField, el cual a su vez tendrá un KeyListener que a su vez estará escuchando las acciones emitidas dentro de otro evento KeyTyped. Éste último evento será el que llamará al método filtro():
private void jTFfiltrarKeyTyped(java.awt.event.KeyEvent evt) { // Comprobamos que el ButtonGroup que nosotros llamamos bGfiltar tenga // seleccionado alguno de los tres JRadioButtons que le hemos agregado if (bGfiltrar.getSelection()==null) { // Si ninguno de los JRadioButtons está seleccionado, evitamos que se // escriba algo dentro del JTextField y mostramos un mensaje de error evt.consume(); JOptionPane.showMessageDialog(this, "Debe seleccionar una opción del filtro", "Menaje de Error", JOptionPane.ERROR_MESSAGE); } else { // Añadimos al JTextField un KeyListener con un KeyAdapter. De esta // forma es como si dieramos enter cada vez que digitamos una techa jTFfiltrar.addKeyListener(new KeyAdapter() { @Override public void keyTyped(final KeyEvent e) { // Llamamos al método encargado de realizar el filtro filtro(); } }); // Inicializamos el objeto trsfiltro de la clase TableRowSorter con // el modelo de la tabla, que para nuestro caso es tabladatos trsfiltro = new TableRowSorter(tabladatos); // Añadimos al Jtable el filtro trsfiltro jTdatos.setRowSorter(trsfiltro); } }
El cĂłdigo completo (omitiendo algunas partes del cĂłdigo generado por NetBeans) quedarĂa de la siguiente forma:
package filtrarjtable; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import javax.swing.JOptionPane; import javax.swing.RowFilter; import javax.swing.UIManager; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableRowSorter; /** * * @author Andres */ public class Interfaz extends javax.swing.JFrame { private DefaultTableModel tabladatos; private TableRowSorter trsfiltro; /** * Creates new form Interfaz */ public Interfaz() { initComponents(); setModeloTabla(); cargarDatos(); } public final void setModeloTabla() { // Inicializamos el modelo de la tabla tabladatos = new DefaultTableModel(); // Creamos los tĂtulos de la tabla y los insertamos en el modelo String[] titulostabla = {"IdentificaciĂłn","Nombre","ProfesiĂłn"}; tabladatos.setColumnIdentifiers(titulostabla); // Insertamos el modelo creado en el JTable this.jTdatos.setModel(tabladatos); } public void cargarDatos() { // Creamos una matriz con los datos que llenarán la tabla Object[][] datos = { {98735671,"Felipe Gomez","Arquitecto"}, {56319046,"Sandra Rios","Docente"}, {11653215,"Camilo Rodriguez","Ingeniero"}, {83211674,"Maria Lopez","Oficial de Policia"}, {76325901,"David Ospina","Docente"}, {90119740,"Hector Cortes","Ingeniero"}, {65267938,"Laura Martinez","Docente"}, {10941507,"El Javatar","Ingeniero"}, {30297534,"Camila Salas","Oficial de Policia"}, {28016745,"Pedro Fernandez","Arquitecto"}, }; // Recorremos las filas de la matriz para ir llenando la tabla for (Object[] dato : datos) { tabladatos.addRow(dato); } } public void filtro() { //Obtenemos el valor del JTextField para el filtro String filtro = jTFfiltrar.getText(); // Comprobamos if (jRBident.isSelected()) { int columna = 0; trsfiltro.setRowFilter(RowFilter.regexFilter(filtro, columna)); } else if (jRBnombre.isSelected()) { int columna = 1; trsfiltro.setRowFilter(RowFilter.regexFilter(filtro, columna)); } else if (jRBprofesion.isSelected()) { int columna = 2; trsfiltro.setRowFilter(RowFilter.regexFilter(filtro, columna)); } } private void initComponents() { // ... CĂłdigo generado por NetBeans } private void jTFfiltrarKeyTyped(java.awt.event.KeyEvent evt) { // Comprobamos que el ButtonGroup que nosotros llamamos bGfiltar tenga // seleccionado alguno de los tres JRadioButtons que le hemos agregado if (bGfiltrar.getSelection()==null) { // Si ninguno de los JRadioButtons está seleccionado, evitamos que se // escriba algo dentro del JTextField y mostramos un mensaje de error evt.consume(); JOptionPane.showMessageDialog(this, "Debe seleccionar una opciĂłn del filtro", "Menaje de Error", JOptionPane.ERROR_MESSAGE); } else { // Añadimos al JTextField un KeyListener con un KeyAdapter. De esta // forma es como si dieramos enter cada vez que digitamos una techa jTFfiltrar.addKeyListener(new KeyAdapter() { @Override public void keyTyped(final KeyEvent e) { // Llamamos al mĂ©todo encargado de realizar el filtro filtro(); } }); // Inicializamos el objeto trsfiltro de la clase TableRowSorter con // el modelo de la tabla, que para nuestro caso es tabladatos trsfiltro = new TableRowSorter(tabladatos); // Añadimos al Jtable el filtro trsfiltro jTdatos.setRowSorter(trsfiltro); } } /** * @param args the command line arguments */ public static void main(String args[]) { // ... CĂłdigo generado por NetBeans } // Variables declaration - do not modify private javax.swing.ButtonGroup bGfiltrar; private javax.swing.JLabel jLabel1; private javax.swing.JRadioButton jRBident; private javax.swing.JRadioButton jRBnombre; private javax.swing.JRadioButton jRBprofesion; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JTextField jTFfiltrar; private javax.swing.JTable jTdatos; // End of variables declaration }
Ejecutamos el proyecto y listo. Próximamente estaré publicando el video donde muestro paso a paso la realización de este proyecto.
hola: es muy interesante. Pero digamos que quiero que no sea sensible a mayusculas y minusculas? Porque lo interesante de esto es que hace el trabajo por ti, porque sino seria hacer un metodo pero seria mas trabajoso. Gracias.
ResponderBorrarHola Jesus. Para hacerlo de forma tal que no sea sensible a mayĂşsculas y minĂşsculas, sĂłlo hay que anteponer "(?i)" en donde obtenemos el texto ingresado en el JTextField dentro del mĂ©todo filtro(). QuedarĂa entonces de la siguiente forma:
ResponderBorrarString filtro = "(?i)"+jTFbuscar.getText();
Espero que te sirva. Saludos
Excelente, me ha servido, muy Ăştil!!
ResponderBorrarMuy bueno el ejemplo!
ResponderBorrarhola podria ayudarme yo intento guardar en un label el valor filtrado mediante un set text pero me da el valor del primer registro de la tabla
ResponderBorrarPara Guardar el valor filtrado dentro de un JLabel, lo que hay que hacer es asignarselo cuando se captura en el mĂ©todo filtro, es decir, despuĂ©s de la lĂnea:
ResponderBorrarString filtro = jTFfiltrar.getText();
Colocamos:
miJLabel.setText(filtro);
Hola me ha servido de mucho su ejemplo, muchas gracias.
ResponderBorrarPero quisiera pedir de su ayuda para recuperar los valores de toda la fila en Strings.
Antes usaba el getSelectedRow Pero ese ahora ya no me sirve.
Con el mĂ©todo getSelectedRow() obtenemos el Ăndice de una fila que estĂ© seleccionada en la Tabla; por tanto, si no hay ninguna fila seleccionada, Ă©ste mĂ©todo nos devolverá por defecto el valor -1.
ResponderBorrarPara obtener todos los valores de una fila en Strings debemos hacerlo a travĂ©s de un ciclo, y podemos recuperarlos desde el JTable o desde el DefaultTableModel. Lo harĂamos de la siguiente forma:
int fila = jTable.getSelectedRow();
String valores = "";
for (int i = 0; i < = jTable.getColumnCount(); i++) {
valores += "" + jTable.getValueAt(fila, i).toString();
valores += " - ";
}
System.out.println(valores);
Lo que hacemos con este ciclo, es recorrer a travĂ©s de un ciclo for todas las columnas de la Tabla, e ir obteniendo los valores de una fila especĂfica a travĂ©s del mĂ©todo getValueAt(row, column)
Espero que te haya ayudado
Saludos hermano ...
ResponderBorrardonde estas llamando el método jTFfiltrarKeyTyped???
gracias
En el paso 6, cuando añadimos el evento al JTextField, NetBeans nos genera automáticamente el método jTFfiltrarKeyTyped y agrega el respectivo evento KeyListener al JTextField en donde llama a dicho método. Esto se puede ver dentro del método initComponents() que es auto-generado por NetBeans
ResponderBorrarquiero consultar en un jtable en un rango de fechas con netbeans, alguien me puede explicar como se hace.
ResponderBorrarCuando busco con signo MAS o ASTIRISCO me da error
ResponderBorrarAmigo disculpe y si quisiera reiniciar la consulta y devolver los valores iniciales por medio de un boton?
ResponderBorrarSerĂa inicializar de nuevo el TableRowSorter:
Borrartrsfiltro = new TableRowSorter(tabladatos);
jTdatos.setRowSorter(trsfiltro);
disculpa por mi ignorancia soy nuevo en esto pero en cargar datos como obtengo lo de la base de datos ?
ResponderBorrarArmando, este es un ejemplo que se enfoca en como filtrar unos resultados ya obtenidos dentro de un JTable, y por eso, a modo de ejemplo coloco unos datos quemados que le asigno a la variable datos de tipo Object[][].
BorrarSin embargo, para darte idea, podrĂas hacer lo siguiente:
- Creas una clase donde tengas la lĂłgica de conexiĂłn a la base de datos.
- Creas una clase (Que serĂa tu DAO), la cual tendrĂa una asociaciĂłn de la clase que creaste previamente para la lĂłgica de tu base de datos.
- En tu clase DAO crearĂas el mĂ©todo con la query que retornarĂa tus resultados de la base de datos, y como para este ejemplo se requiere de un valor de tipo Object[][], debes mapear tus resultados en una variable de este tipo y retornarlo mediante el mĂ©todo.
A grandes rasgos, eso es lo que podrĂas hacer para obtener los datos desde la base de datos
sobre esta Ăşltima respuesta (del 5 de junio de 2019) ¿podrĂas darme un ejemplo de cĂłmo hacerlo? más precisamente la parte de "debes mapear tus resultados en una variable de este tipo y retornarlo mediante el mĂ©todo."
Borrarporque reemplacé el contenido de cagardatos() por
try {
Class.forName("org.sqlite.JDBC");
Connection con = DriverManager.getConnection("jdbc:sqlite:/home/leo/java/Fiesta.db");
String sql = "SELECT * FROM Clientes";
PreparedStatement pst = con.prepareStatement(sql);
ResultSet rs = pst.executeQuery();
jTdatos.setModel(DbUtils.resultSetToTableModel(rs));
}
catch (SQLException ex){
System.out.println("Mensaje:"+ex.getMessage());
} catch (ClassNotFoundException ex)
{
}
pero obviamente no funcionĂł.
Desde ya, muchas gracias
Desde ya, muchas gracias
Leonardo, despuĂ©s de la lĂnea "jTdatos.setModel(DbUtils.resultSetToTableModel(rs));" deberĂas actualizar el Modelo de datos con esta instrucciĂłn:
BorrartableModel.fireTableDataChanged();