lunes, 9 de julio de 2018

Modificar una cadena en JList y en JComboBox

En clase me han preguntado como puedo modificar una cadena dentro de un componente Swing como ComboBox. Juguemos un poco con estas ideas que son muy interesantes.

Cuando trabajamos en un entorno gráfico con swing y queremos gestionar una lista de elementos tipo String habitualmente usamos un JList o un JComboBox. Esta gestión es muy sencilla en ambos componentes tanto para añadir como para eliminar elementos.

El problema viene cuando tenemos una lista de Strings y queremos modificar uno de ellos. Veamos la situación y la solución.

Trabajo con JList
En el caso del JList es imprescindible usar un modelo asociado, es decir, una colección de elementos que se encarga de gestionar los datos y según cambie dicha colección cambia el aspecto visual del JList. Se podría usar sin modelo pero entonces el JList no es modificable.
Veamos un ejemplo, crea una clase Formulario que herede de JFrame de la siguiente forma:

import java.awt.*;
import javax.swing.*;

public class Formulario extends JFrame {
    JList<String> lst;
    DefaultListModel<String> modeloLista;

    public Formulario()  {
        super();
        setLayout(new FlowLayout());
        
        String[] dias={"Lunes", "Martes", "Miércoles", "Jueves",
                        "Biernes", "Sábado", "Domingo"
        };
        modeloLista= new DefaultListModel<>();
        lst= new JList<>(modeloLista);
        add(lst);
        
        for (String s:dias){
            modeloLista.addElement(s);
        }
    }

}

Si conoces los conceptos básicos del JList el código anterior no debería de tener mayor problema salvo el de las ganas de arrancarse los ojos al ver escrito uno de los días de la semana con B en lugar de con V.

Por supuesto, en una clase aparte escribe el main:

import javax.swing.*;

public class Principal {

public static void main(String[] args) {
            Formulario frame = new Formulario();
        
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(200, 200);   
            frame.setVisible(true);
}

}

Bien ¿Cómo podemos arreglar el problema del Biernes/Viernes? Como sabemos el tipo String es inmutable, es decir, no podemos acceder a su primera posición y cambiar la B por la V. Pero podemos cambiar la palabra entera a través del modelo. Es decir, puedo escribir:

        modeloLista.setElementAt("Viernes", 4);


Y ya estaría corregido. De esta forma el método setElement soluciona nuestro problema de forma muy sencilla.

Trabajo con JComboBox
Tratemos de repetir lo anterior con JComboBox. Lo primero que se nos ocurrirá es usar el JComboBox de forma directa y veremos que se permite añadir y eliminar items pero no modificarlos. Por tanto una solución sería quitar el incorrecto e insertar el correcto. Veámoslo:

public class Formulario2 extends JFrame {
    JComboBox<String> cb;

    public Formulario2()  {
        super();
        setLayout(new FlowLayout());
        
        String[] dias={"Lunes", "Martes", "Miércoles", "Jueves",
                        "Biernes", "Sábado", "Domingo"
        };        
        cb= new JComboBox<>(dias);
        add(cb);
        
        cb.removeItemAt(4);
        cb.insertItemAt("Viernes",4);
    }

}

También muy sencillo. Incluso se podría hacer también a través del modelo.

¡Pero yo quiero cambiar la cadena por dentro!
Pues no puedes. Bueeeno, sí pero entonces tenemos que acudir a otra clase. Es decir, no podemos usar String porque String es inmutable. Esto como ya comenté implica que una vez creado no puede modificarse. Se le podrá asignar un String distinto, pero el previo no puede ser modificado.
Por tanto si necesitamos hacer cambios a bajo nivel en una cadena lo que tenemos que hacer es usar un StringBuilder que es un tipo String pero mutable. Es más incómodo para ciertas tareas pero más versátil y potente.
El siguiente ejemplo muestra como usarlo:

public class Formulario3 extends JFrame {
JComboBox<StringBuilder> cb;

    public Formulario3()  {
        super();
        setLayout(new FlowLayout());
       
        StringBuilder[] dias={
        new StringBuilder("Lunes"),
        new StringBuilder("Martes"), 
        new StringBuilder("Miércoles"), 
        new StringBuilder("Jueves"),
        new StringBuilder("Biernes"),
        new StringBuilder("Sábado"), 
        new StringBuilder("Domingo")
        };        
        cb= new JComboBox<>(dias);
        add(cb);

        cb.getItemAt(4).setCharAt(0,'V');

    }

}

Se puede observar que la creación es más compleja ya que hay que realizar un new por cada cadena . En el caso del String no es necesario porque a un String siempre le asignamos u otro String que ya existe en memoria o un literal String que reserva memoria en tiempo de compilación.
Sin embargo StringBuilder no, es una clase "normal" y hay que reservar memoria para ella, de ahí que se complique la creación del array dias.
Sin embaargo una vez creado el combo con sus cadenas, se puede modificar mediante diversas funciones como setCharAt, insert, delete, etc...
Si en lugar de un carácter quisiéramos cambiar varios podríamos hacer lo siguiente:

        cb.getItemAt(4).deleteCharAt(0);
        cb.getItemAt(4).insert(0,"Viii");

Estas dos líneas sustituirían a la del método setCharAt.

Puedes ver el proyecto para Eclipse en el siguiente enlace.

¡Hasta el próximo post!

No hay comentarios:

Publicar un comentario