GUI Dinámica
Se llama GUI dinámica a una interfaz que crea o elimina componentes en tiempo de
ejecución. Se suelen utilizar para representar listas de elementos, y aunque se pueden
realizar mediante algún atajo (modificando la visibilidad de componentes o paneles en
tiempo de ejecución), normalmente se utiliza algún tipo de componente personalizado que
se añade dinámicamente a una sección de la GUI. Cada elemento suele ser un panel que
contiene otra serie de componentes.
En la siguiente imagen vemos un programa de descargas, cuyo panel central va añadiendo
nuevos elementos (subpaneles de descarga), conforme se van poniendo en cola más
descargas:
En el video que se incluye a continuación se muestra un ejemplo de creación de una interfaz
dinámica:
En el siguiente video, además de usar una interfaz dinámica gestionamos los eventos de
nuestro componente personalizado mediante el Event Dispatcher:
ListCellRenderers: personalizar JList y JComboBox
Otra forma de usar componentes personalizados para listar elementos es hacer que un
elemento JList o JComboBox muestre nuestros componentes en sus celdas. Es decir,
diseñar el aspecto de las celdas de JList, por ejemplo. Para ello nuestro componente debe
implementar la interface ListCellRenderer .
Podemos hacer, por ejemplo, que cada celda de un JList o JComboBox tenga además del
texto, una pequeña imagen. El elemento gráfico que permite tener una imagen y un texto es
el JLabel. Por lo tanto tenemos que crear nuestro componente personalizado a partir de la
clase JLabel y que dicha clase implemente ListCellRenderer. La idea es la misma si
queremos usar un JPanel personalizado.
En el método getListCellRendererComponent() que nos implemente la interface, aunque
parezca complejo, tan solo tenemos que dar valor a las dos propiedades de la JLabel que
nos interesan: el texto y la imagen.
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
public class PaisRenderer extends JLabel implements
ListCellRenderer<Pais> {
public CountryRenderer() {
//Indico que la JLabel no es transparente
setOpaque(true);
//Método implementado por la interface ListCellRenderer
@Override
public Component getListCellRendererComponent(JList list, Object
value, int index,
boolean isSelected, boolean cellHasFocus) {
//Lo único que hay que hacer es indicar los valores que tendrá
JLabel
Pais pais = (Pais) value;
//Si renderizo en un comboBox, compruebo si pais es null
String nombreImagen = [Link]();
ImageIcon imageIcon = new
ImageIcon(getClass().getResource("/images/" + nombreImagen + ".png"));
//Añado la imagen correspondiente a la JLabel
setIcon(imageIcon);
setText([Link]());
//Indico los colores de fondo de los elementos seleccionados y no
seleccionados
if (isSelected) {
//Usa por defecto los que use el JList
setBackground([Link]());
setForeground([Link]());
} else {
setBackground([Link]());
setForeground([Link]());
//Devuelvo el objeto PaisRenderer
return this;
}
En el ejemplo anterior se usa un componente personalizado (JLabel) para representar
países en una lista. La clase Pais solo tiene dos atributos: nombre y nombreImagen.
En caso de que el renderer se use para un JComboBox debo añadir en el método
getListCellRendererComponent() un control sobre valores null antes de realizar las
demás instrucciones:
//Compruebo si el valor es null
if(value == null){
setIcon(null);
setText("");
} else {
Pais pais = (Pais) value;
String nombreImagen = [Link]();
. . .
Para usar el JList o un JComboBox con el Renderer creado:
JList<Pais> lista = new JList<Pais>();
DefaultListModel<Pais> dlm = new DefaultListModel<Pais>();
//Asocio el renderer
[Link](new PaisRenderer());
//Ahora usamos el modelo de forma habitual:
[Link](unPais);
Las celdas de JList o JComboBox solo sirven para mostrar información; No son elementos
interactivos. Si nuestros componentes tienen funcionalidad extra (p.e. botones), estos
botones aparecerán, pero no se podrán usar.