lunes, 24 de enero de 2011

Cómo seleccionar una fila de un JTable de Java

A veces nos vemos en la necesidad de seleccionar o resaltar mediante código una fila de un JTable, ya sea porque necesitamos realizar una búsqueda en la tabla o por cualquier otro motivo. Si el JTable se encuentra dentro de un JScrollPane, las barras de desplazamiento se deben mover automáticamente para que se vea la fila que se seleccionó.

Para realizar ésta tarea tenemos el método changeSelection de la clase JTable, el cual cuenta con 4 parámetros: rowIndex, columnIndex, toggle y extend; los dos primeros son dos números enteros que indican la fila y columna de la celda, mientras que toggle y extend son booleanos que sirven para indicar si queremos seleccionar una fila, un rango de filas o varias filas.

Para entender mejor el funcionamiento de éste método realizaremos un ejemplo práctico, que consistirá en realizar la búsqueda de un elemento químico dentro de una tabla. Es decir tendremos una tabla con cierta cantidad de elementos químicos, para buscar un determinado elemento deberemos introducirlo dentro del campo de texto respectivo, seguidamente deberemos presionar el botón Buscar e inmediatamente se resaltará la fila en la cual se encuentra el dato que estábamos buscando (si fue encontrado).

La interfaz gráfica quedaría como sigue:
Como vemos en la anterior imagen buscamos el elemento "Decano" que se encuentra a lo último de la tabla, por lo que las barras de desplazamiento se movieron automáticamente hasta hacer visible la fila donde se encuentra el dato.

Si realizamos una nueva búsqueda, la fila seleccionada anteriormente se deseleccionará y se seleccionará la fila donde se encuentra el dato de la última búsqueda, como podemos ver en la siguiente imagen:
El código que va dentro del botón Buscar para realizar este programa es el siguiente:
private void btnBuscarActionPerformed(java.awt.event.ActionEvent evt) {                                     

    String ele = txtElemento.getText();

    for (int i = 0; i < tbComponentes.getRowCount(); i++) {
           if (tbComponentes.getValueAt(i, 1).equals(ele)) {                                           
                  tbComponentes.changeSelection(i, 1, false, false);
                  break;
           }
    }
}
Del anterior código podemos observar en la línea de código 7 que los parámetros toggle y extend del método changeSelection deben estar en false, para trabajar de la manera que nos propusimos en el ejemplo: mantener seleccionada solamente una fila por cada búsqueda.

Sin embargo puede haber otras ocasiones en las que se necesita seleccionar más de una fila a la vez, para ello pueden "jugar" con el código de ejemplo que les estoy pasando, cambiando los valores de los parámetros toggle y extend para poder visualizar mejor qué "papel juegan" dentro del método.

Les recomiendo leer la documentación oficial del método changeSelection de la clase JTable, donde encontrarán una breve explicación sobre el mismo y sus parámetros.

No se preocupen que no me olvido de dejarles el código fuente programado en Java utilizando NetBeans 6.5 para que puedan practicar. Espero les haya sido de utilidad, cualquier acotación o aporte será bienvenido, hasta la próxima.

Código Fuente: download/descargar

48 comentarios:

  1. Interesante. Pese a que no manejos éstos programas siempre es de agradecer. Saludos y buena semana.
    Ramón

    ResponderEliminar
  2. Gracias amigo! Me sirvió de mucho.

    ResponderEliminar
  3. gracias amigasoo muchas gracias

    ResponderEliminar
  4. gracias sube mas proyectos de botones de busqueda

    ResponderEliminar
  5. donde puedo seguir buscando mas proyectos de java en netbeans

    ResponderEliminar
  6. gracias gracias gracias :)

    ResponderEliminar
  7. Excelente código, pero quisiera saber como haria para arrojar un mensaje en caso de que no se encuentre nada en la tabla...

    Saludos

    ResponderEliminar
  8. Con JOptionPane claro. Una idea así a vuelo de pájaro, declara una variable boleana como false (no encontrada) antes de entrar al for, luego si encuentra el elemento en el if correspondiente antes del break pon esa variable como true (encontrada). Al finalizar el for pregunta si la variable está en false, si es así, muestra un mensaje con JOptionPane; caso contrario no hagas nada.

    Salu2.

    ResponderEliminar
  9. Gracias amigo por responder, este es el código al cual le agregué la variable booleana como me indicaste:

    public void seleccionarTabla(JTable mitabla,JTextField jt){
    int fil, col;
    boolean encontrado=false;


    //Limpia selección de la tabla
    try{
    String ele = jt.getText();

    for (int i = 0; i < mitabla.getRowCount(); i++) {
    if (mitabla.getValueAt(i, 0).equals(ele)) {
    mitabla.changeSelection(i, 1, false, false);
    encontrado=true;
    break;
    }
    }
    if(!encontrado){
    JOptionPane.showMessageDialog(null, "No existe el registro");
    }

    }catch(NullPointerException ex){

    }
    }

    pero no arroja el mensaje, sin embargo cuando la variable es true si lo hace.

    Ayuda por favor...!

    ResponderEliminar
  10. Está bien eso que hiciste, me entendiste bien las instrucciones que te dí, en tu código que me muestras no veo en qué estás fallando, pero yo ya lo probé aumentando lo que faltaría en el código que les muestro en este artículo, sigue intentando, pero sino puedes si quieres deja tu correo para que te lo envíe.

    ResponderEliminar
  11. Muchas gracias, mi correo es: fahalak@cantv.net

    Saludos

    ResponderEliminar
  12. Amigo el código que me enviaste funcionó a la perfección. Agradecido

    ResponderEliminar
  13. Exelente información, gracias...

    quiciera saber como puedo seleccionar varios datos duplicados o repetidos, es decir despues de que seleccione el primer dato de la busqueda como puedo seguir seleccionando los datos duplicados.

    ResponderEliminar
  14. Por eso les decía jueguen con los parámetros "toggle" y "extend" del método "changeSelection", con ellos obtendrás las selecciones deseadas, ya sea una sola fila, un rango de filas, o varias filas.

    En tu caso quita la instrucción "break" que se encuentra dentro del "if" y reemplaza el método "tbComponentes.changeSelection(i, 1, false, false)" por "tbComponentes.changeSelection(i, 1, true, false)".

    Ahí me cuentas cómo te fue, suerte.

    ResponderEliminar
  15. Perfecto, funciono de maravilla, claro tocaba quitar el break, pero no sabia como utilizar el toggle y extend de dicha funcion, ya que hasta ahora etoy aprendiendo a manejar las tablas.

    gracias amigo, muy útil.

    ResponderEliminar
  16. Gracias hermano, me ha sido de mucha ayuda en un proyecto final!

    saludos!!

    ResponderEliminar
  17. hola colega..espero puedas darme una mano con esto y gracias de antemano... tengo un jtable con datos cargados desde una BD...yo quisiera q cuando escriba "MAN" sobre el jtable , se seleccione la fila que contiene "MANCHAS" pero sin usar un jtext ni nada,sino sobre el mismo jtable. Espero me puedas ayudar

    ResponderEliminar
  18. @Valsrock, utiliza los eventos del teclado sobre el JTable, el método keyTyped de la interfaz KeyListener te serviría bastante bien, en ese método utiliza una variable global de tipo String en la que vayas concatenando cada tecla que va presionando el usuario cuando hace click en cualquier lugar del JTable, inmediatamente después de realizar la concatenación realizas la búsqueda con el contenido de esa variable global en el JTable, tal y como se muestra en la ejemplo de este artículo.

    Cada vez que el usuario necesite realizar una nueva búsqueda puedes hacer que realice un click sobre el JTable y la variable global de tipo String se reinicie como vacía. O mejor aún puedes utilizar un Timer, y por ejemplo, verificar cada 3 segundos si el usuario no ha tecleado ninguna palabra, en ese caso reiniciar la variable global de tipo String y reiniciar el Timer para realizar un nuevo conteo, en caso contrario seguir con la concatenación y la búsqueda. De esta manera podrás realizar búsquedas mientas escribes sobre un JTable o algo similar al buscador de Google, pero directamente sobre el JTable como lo que necesitas.

    Saludos!!!

    ResponderEliminar
  19. Muy bueno ya lo aplique y funciona a la perfeccion

    ResponderEliminar
  20. Oyes gracias por la info , como puedo concatenar lo registros, lo que quiero es buscarlo por sus de mas campos.

    ResponderEliminar
    Respuestas
    1. Pero para eso no necesitas concatenarlos, aumenta un and (&&) en la sentencia if, por ejemplo: if (tbComponentes.getValueAt(i, 1).equals(ele) && tbComponentes.getValueAt(i,2).equals(simb))

      De esta manera el ejemplo del código que les presente en este artículo buscaría filas que contengan un elemento determinado "ele" y además que tengan un símbolo determinado "simb".

      Eliminar
  21. Gracias por tu aporte me ayudaste mucho saludos!

    ResponderEliminar
    Respuestas
    1. Qué bueno, pero no se olviden de calificar el post por favor.

      Eliminar
  22. como puedo hacer para que no sea necesario ingresar tal cual el nombre, es decir si pongo por ejemplo "Daniela" que me lo busque si lo ingreso tanto en minuscula como mayuscula??? o tmb si tiene apellido que no sea necesario que ingrese todo completo sino mas bien una parte

    ResponderEliminar
    Respuestas
    1. Para el primer caso utiliza el método equalsIgnoreCase en vez de equals y para el segundo caso puedes usar expresiones regulares o patrones de coincidencia.

      P.D.- Insisto, no se olviden de calificar el artículo por favor.

      Eliminar
  23. gracias me ayudaste a solucionar una duda, pero como le haria si quiero buscar un numero en vez de caracter??????? ojala podas ayudarme orale

    ResponderEliminar
  24. Oh, Gracias bro! sos grande, me ayudó mucho esta info, especialmente el codigo para buscar...

    ResponderEliminar
  25. Buenos dias, como puedo hacer para que en un jtable pueda cambiar de color la ultima celda que se esta ingresando, los datos se ingresan con un resultset y estoy usando timer y quiero mostrar a la vista los cambios q se producen en dicha tabla... Se lo agradeceria.

    ResponderEliminar
    Respuestas
    1. Hola, no entiendo muy bien tu pregunta, podrías ser un poco más explícito???, y al decir "la última celda" te refieres a la última fila???

      Eliminar
    2. ok, tengo un jtable que me esta mostrando una serie de articulos y tengo un boton de iniciar, cuando yo le doy a ese boton el hace la consulta constantemente y me esta refrescando la tabla continuamente hasta que yo le de detener, si consigue articulos nuevos en esa consulta el actualiza la tabla pero quiero q si hay informacion nueva se me muestre en otro color para q se vea la actualizacion.

      Eliminar
    3. Utiliza el id o código de artículo (la llave de tu tabla "artículo" de tu base de datos) en una columna del jTable, de esta manera cada vez que consultes los artículos de la base de datos verifiques que no exista en tu jtable utilizando el "código de artículo", si no existe una fila en el jTable que tenga el mismo "código de artículo" lo adicionas al jTable y pintas la nueva fila o la seleccionas o resaltas con tuTabla.changeSelection(indNuevaFila, 1, true, false)

      En resumen la idea general es que por cada artículo que consultes en la base de datos debes verificar (utilizando un id o código) que este no exista en el jTable, de confirmarse que no existe adicionas una nueva fila y la pintas o resaltas.

      Eliminar
    4. Gracias por tu ayuda.... Estoy tratando de ubicarme, pero soy algo nueva en esto, con lo que tu me has dicho he hecho algo como esto:

      public class Render extends DefaultTableCellRenderer {
      public Component getTableCellRendererComponent (JTable jTable1, Object value, boolean selected, boolean focused, int row, int column )
      {
      // Component cell= super.getTableCellRendererComponent(jTable1, value, selected, focused, row, column)
      setEnabled(jTable1 == null || jTable1.isEnabled());
      // see question above
      {
      for (int i=0; i<jTable1.getRowCount();i++){
      if (jTable1.getValueAt(i,0).equals(jTable1.getValueAt(i,0))){
      setBackground(null);

      } else setBackground(Color.BLUE);
      jTable1.changeSelection(jTable1.getRowCount(), 0, true, false);
      }
      super.getTableCellRendererComponent(jTable1, value, selected, focused, row, column);
      return this;
      }
      }
      }

      pero no se como obtener el indice de la nueva fila, no se si lo estoy haciendo bien.... Sera que me puedes ayudar... Te lo agradeceria.

      Eliminar
    5. Bueno, como eres "algo nueva" mejor usa directamente tuTabla.changeSelection(indNuevaFila,0, true, false) y no te compliques con DefaultTableCellRenderer, donde:

      indNuevaFila = tuTabla.getRowCount() - 1; ya que el índice de la fila en un jTabla va entre 0 y (Nro_Filas - 1) y cada fila nueva que vas adicionando siempre será la última ¿verdad?.

      Cualquier duda que tengas ahí me cuentas que por aquí estaré.

      Eliminar
  26. Muy bueno amigo, solo señalar que para que no haya confusión tbCompnonetes viene a ser el jTable je je

    ResponderEliminar
  27. Buenas, estoy trabajando con tablas con un defaulttablemodel con vectores, pero no me quiere mostrar nada en la vista, aca les dejo el codigo para que vean como lo estoy haciendo y a ver si me pueden decir q me hace falta para q me lo muestre....
    productos= new Vector();
    productos=setValueVector("SelectItemReplacement()");

    columnas=new Vector();
    columnas=FillVector("Codigo de Articulo,Descripcion de Articulo,Stock Minimo,Stock Maximo,Unidades Vendidas,Ubicacion del Articulo,Cantidad a remplazar,Stock,Reemplazado");
    modelo= new DefaultTableModel(productos,columnas){
    public Class getClumnClass(int c){
    return getValueAt(0,c).getClass();
    }
    };

    jTable1 = new JTable();
    jTable1.setModel(modelo);

    donde fillvector y setvaluegeneral son metodos que me llenan esos vectores....

    ResponderEliminar
    Respuestas
    1. Nunca había visto esa forma de trabajar con jTable, pero si lo que tienes es problema con la vista, prueba usando jTable1.repaint(), sino te funciona prueba con jTable1.updateUI() o una combinación de ambos, suerte!!!

      Eliminar
  28. Hola Cero Cool
    Soy nuevo en esto
    Tengo unas dudas de como seleccionar directamente de una JTable un campo por ejemplo un id/codigo y pasarselo a otra JTable,con un doble clic por ejemplo. Si tienes unos ejemplos de esos me ayudaría un monton.
    PD: Exelente el articulo
    Saludos

    ResponderEliminar
    Respuestas
    1. En el sgte. link puedes ver cómo controlar el doble clic en Java: Doble Clic en Java, solo que en tu caso tendrás que usar el evento del mouse del jTable.

      Una vez detectado el doble clic dentro del método que controla los eventos del ratón en el jTable1, utiliza el método int fil = jTable1.getSelectedRow(); el cual te devolverá la fila que ha seleccionado el usuario. Seguidamente utiliza el método int id = (Integer) jTable1.getValueAt(fil, 0); el cual te devolverá el id si es que éste se encuentra en la columna 0 del jTable1, y finalmente podrás codificar un método que te copie ese dato a una jTable2.

      Espero que te sirva la guía, saludos.

      Eliminar
  29. Muchas gracias por la ayuda,cualquier duda que me salga te aviso.
    PD: La linea int id = (Integer) jTable1.getValueAt(fil, 0); me salia con un error y probé con int id = Integer.valueOf((String) jTable.getValueAt(fil, 0)); y se arreglo el problema, por si te sirve.
    Saludos

    ResponderEliminar
  30. Me olvide comentarte que utilizo eclipse por si las dudas de que por eso salte el problema.
    Saludos

    ResponderEliminar
  31. Excelente post! me vino justo.
    Con que evento puedo modificar una fila o alguna columna del jtable que toma los datos de mysql? para hacer un update directamente o en todo caso moverlos a los textfield que uso para insertar en la misma pantalla? gracias.

    ResponderEliminar
    Respuestas
    1. No importa de dónde tome los datos el JTable, ya sea de una base de datos o de donde sea, para modificar o actualizar una fila o columna de la tabla existe el método setValueAt(Object aValue, int row, int column)

      Eliminar
  32. AMIGO MUCHISIMAS GRACIAS QUE EXCELENTE TUTORIALES
    Y COMO SE PUEDE COLOCAR JCHECBOX DENTRO DE UN JTABLE JAVA?? QUE ESTA LLENA POR LA BASE DE DATOS ?? SE PUEDE??? COMO SE HACE PORFAVOR vvvvianey@gmail.com

    ResponderEliminar

Encuesta: ¿Quién es el mejor catedrático de la carrera de Ing. Informática de la UAGRM?