Aún recuerdo cuando comencé a utilizar componentes en Swing, anteriormente programa las interfaces a mano peleando contra la filosofía de el para que reinventar la rueda, hasta que me canse y decidí ser más eficientes que orgulloso, en fin, fue un cambio por completo para mi, ya que estaba acostumbrado a programar lo que quería a mano, y las interfaces en Swing a mano suelen funcionar algo diferentes a cuando las hacemos con algún asistente, ya que lo mejor es utilizar modelos en un asistente, y al final de cuentas te das cuenta que es más accesible, en esta ocasión, les enseñaré la manera correcta de utilizar un JList de Swing para que puedan manipularlo a su gusto y puedan utilizarlo para acceder a elementos de bases de datos, etc, y sin ningún problema, pero, antes que nada, les enseñaré lo más básico que puede haber con este componente, y es crear un modelo sencillo a mano mediante un método, y hacerle un set al componente para que lo muestre, para esto e hecho lo siguiente, tengo una clase en Netbeans que es un JFrameForm al cual le e agregado un JList sencillo y unas etiquetas para ir procediendo con el ejercicio poco a poco con la intensión de que todo quede sumamente claro:
Bien, ahora veamos algo sencillo, mucha gente utiliza el siguiente método par añadirle contenido a un JList, y es necesario tambien que lo aprendamos por una u otra manera, tengan en cuenta que este método lo borraremos posteriormente, lo primero y lo más fácil de hacer a la hora de manipular un JList es crear un método que nos devuelva un modelo para enviarselo posteriormente al JList, para esto harémos un método que nos devuelva un objeto DefaultListModel, objeto al cual le añadiremos elementos en String que querramos que se muestren en la lista:
private DefaultListModel modelList(){ DefaultListModelmodel = new DefaultListModel<>(); model.addElement("Alumno 1"); model.addElement("Alumno 2"); model.addElement("Alumno 3"); return model; }
Bien, como verán este método en primera instancia crea un objeto DefaultListModel de Strings, y posteriormente, le agrego manualmente los elementos, ahora, solo nos queda añadir la linea al constructor de la clase del JFrame que le envie el modelo al JList que en mi caso tiene como nombre de variable «lista».
lista.setModel(modelList());
Esto, nos daría como resultado algo como lo siguiente:
Bien, esta sería una manera muy sencilla de utilizar el JList, pero ¿Que pasa?, ¿Que sucede si lo que quiero que tenga el JList sean los objetos Alumnos o los objetos Personas que yo tenga en una clase a parte, esto no me serviría, por que si yo le envío los objetos al JList este me mostrará las direcciones de memoria, y a la hora de seleccionar un elemento de la lista, yo no podría saber la información de cada uno de mis objetos, y esto es lo que veremos a continuación, primero que nada, borremos el método que hicimos (era solo un test) y borremos la linea del constructor, y lo que haremos, será crear una clase que representará nuestro modelo personalizado, esta clase heredará de AbstractListModel, un objeto que nos permite crear nuestros modelos personalizados para una lista, este nos pedirá la implementación del método getSize y del método getElementAt:
public class CustomListModel extends AbstractListModel{ @Override public int getSize() { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public Object getElementAt(int index) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } }
También necesitaremos una clase que represente al objeto persona con el cual estaremos trabajando para este ejercicio:
public class Persona { private String nombre,apellidos; private int edad; public Persona(String nombre, String apellidos, int edad) { this.nombre = nombre; this.apellidos = apellidos; this.edad = edad; } public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; } public String getApellidos() { return apellidos; } public void setApellidos(String apellidos) { this.apellidos = apellidos; } public int getEdad() { return edad; } public void setEdad(int edad) { this.edad = edad; } }
Bien, ahora tenemos todo lo necesario para comenzar a trabajar, bien , lo primero que vamos a hacer es trabajar con la clase CustomListModel, y dentro de esta vamos a crear un ArrayList de clase Persona con alcance global, esto lo podemos hacer hasta arriba antes del método getSize sin problemas:
private ArrayListlista = new ArrayList<>();
Bien, una vez teniendo este ArrayList (que bien se puede llenar con la base de datos en lugar de inicializarse vacio), llenaremos los dos métodos que nos obligó a implementar la herencia de AbstractListModel, y esto es muy sencillo de hacer, el método getSize simplemente devuelve el tamaño completo de elementos en el JList, por consecuente, este tamaño será el mismo que el de la longitud de la lista:
@Override public int getSize() { return lista.size(); }
En el método getElementAt observaremos primero que nada que recibimos una posición, esta posición normalmente es la que se encuentrar actualmente seleccionada en el JList, por consecuente, será la misma posición del ArrayList, de esta posición, sacaremos el objeto Persona del ArrayList y retornaremos el valor que querramos que se muestre visualmente en el JList:
@Override public Object getElementAt(int index) { Persona p = lista.get(index); return p.getNombre(); }
Y listo, teóricamente si tuvieramos datos con esto podriamos mostrar los datos sin problemas, pero que pasa, ya que en nuestra interfaz pusimos que vamos a añadir personas a la lista, no podemos añadir solo el nombre, así que vamos a hacer un método que nos permita añadir un objeto Persona a la lista sin ningún problema ¿va?, el método primero que nada tiene que recibir un objeto persona y posteriormente agregarlo a la lista, pero acá vendrá el chiste, tendremos que notificarle a nuestro modelo, que hemos recibido un dato nuevo y que tiene que actualizar lo que se está viendo en este momento:
public void addPersona(Persona p){ lista.add(p); this.fireIntervalAdded(this, getSize(), getSize()+1); }
El método fireIntervalAdded es un método que nos permite notificarle al JList que un elemento ha sido agregado, enviandole un rango de intervalor que en este caso normalmente podemos utilizar getsize() y getsize()+1, datos obtenidos del JList, y listo, con esto estariamos listos, ahora bien, si nosotros quisieramos eliminar un elemento de la lista, necesitariamos un método similar pero que no reciba un objeto, sino solo un indice que sería la posición del elemento seleccionado:
public void eliminarPersona(int index0){ lista.remove(index0); this.fireIntervalRemoved(index0, getSize(), getSize()+1); }
Por ultimo, agregaremos un último método, que nos permitirá acceder a los datos de una de las personas simplemente enviandole el indice que tengo seleccionado, para esto haremos algo muy sencillo, agregaremos un método que nos devuelva un objeto persona pasandole el indice:
public Persona getPersona(int index){ return lista.get(index); }
Y bien, yo creo que con esto sería suficiente para la lista, ahora solo nos queda darle funcionalidad a nuestro pequeño programa, y añadir un botón borrar, que se me paso xD … por lo pronto solo les dejo la clase terminada de CustomListModel:
public class CustomListModel extends AbstractListModel{ private ArrayListlista = new ArrayList<>(); @Override public int getSize() { return lista.size(); } @Override public Object getElementAt(int index) { Persona p = lista.get(index); return p.getNombre(); } public void addPersona(Persona p){ lista.add(p); this.fireIntervalAdded(this, getSize(), getSize()+1); } public void eliminarPersona(int index0){ lista.remove(index0); this.fireIntervalRemoved(index0, getSize(), getSize()+1); } public Persona getPersona(int index){ return lista.get(index); } }
Ahora bien, lo único que si les voy a encargar es que le cambien el nombre a las variables que representarán los campos de texto, en mi caso yo les e puesto campo_nombre, campo_apellidos, campo_telefono y para las etiquetas informacion_nombre, informacion_telefono e informacion_apellidos, y con esto, comenzaremos a trabajar:
Lo primero que haremos será crear una variable global de nuestro modelo sobre el constructor de la clase del JFrame:
CustomListModel list_model = new CustomListModel();
Ahora bajo el initComponents del constructor settearemos el modelo para que el JList ya lo tome por defecto desde que arranquemos la aplicación:
lista.setModel(list_model);
Bien, ahora a darle doble click al botón para añadirle funcionalidad, y el botón hará algo super sencillo, tomar las variables de los campos de texto y con estas crear un objeto persona que le agregaremos al modelo:
int edad = Integer.parseInt(campo_edad.getText()); Persona p = new Persona(campo_nombre.getText(), campo_apellidos.getText(), edad); list_model.addPersona(p);
Y con esto, tendriamos funcionando la aplicación para agregar personas, algo similar a esto:
Bien, ahora vamos a hacer que funcione el botón eliminar, este será muy sencillo, vamos a darle doble click y a darle funcionalidad:
int selection = lista.getSelectedIndex(); if (selection!=-1) { list_model.eliminarPersona(selection); }
Bien, lo que hace el código anterior es muy sencillo, le pedimos a la lista la posición que tiene seleccionada a este momento, el método getSelectIndex nos devuelve -1 si no hay nada seleccionado, por eso el IF, ahora bien, si hay algo seleccionado, simplemente trabajamos con el modelo y le pedimos que lo retire de la lista, y este automaticamente debe de trabajar, por ultimo agregaremos una ultima funcionalidad, la del hecho de que cuando seleccionemos un elemento de la lista, automaticamente nos muestre toda la información de la persona en la parte de abajo, esto lo haremos de la siguiente manera, desde el modo de diseño de nuestro JFrame, vamos a darle click derecho a nuestro JList, y posteriormente buscaremos el menu eventos, dentro de este, ubicaremos un submenu que dice ListSelection y daremos click al elemento ValueChanged, y veremos que pasa:
Netbeans nos envía a un método que se ejecuta automaticamente cuando seleccionamos un elemento de la lista, y bien, este es el que nos permitirá hacer lo que queremos, así en centremonos en que es lo que quisieramos que pase, y lo que quiero que pase, es que dependiendo del que este seleccionado, tomaré un objeto persona ubicado en el mismo indice y mostraré en las etiquetas de información los datos correspondientes, algo muy similar al método anterior, observen:
int selection = lista.getSelectedIndex(); if (selection!=-1) { Persona p = list_model.getPersona(selection); informacion_apellidos.setText(p.getApellidos()); informacion_edad.setText(Integer.toString(p.getEdad())); informacion_nombre.setText(p.getNombre()); }
Y listo, con esto tendremos nuestro programa funcionando, super sencillo, fácil y rápido de hacer, claro que lo idoneo es que los datos se vayan agregando a una base de datos y toda la onda, pero es la misma idea.