Lo de guardar en disco, es porque para poder poner a prueba el programa, sería terrible que cada vez que iniciamos el programa, tuviéramos que registrar nuevos usuarios y registrar nuevos eventos, para comprobar si lo último que hemos añadido funciona bien o no.
Así que, o guardamos en disco los usuarios y eventos que iremos generando...
O bien, generamos por código una serie de usuarios y eventos.
En mi código ya has visto que si no hay datos guardados en disco, genero automáticamente un usuario Administrador.
Pues igual que genero uno, podemos generar mediante código 10, 20.. los que queramos.
Si crees que por añadir lo de guardar en disco te lo van a cuestionar por ser algo que aún no te han explicado, puedes optar por lo de generar usuarios mediante código.
Si mantienes lo de guardar en disco, asegúrate de que entiendes bien como funciona, por si te lo preguntan, pues que puedas explicarlo.
Tu pregunta por aquí cualquier cosa que no entiendas. Todo lo que voy añadiendo intento explicarlo paso a paso, pero puede que algo requiera explicaciones extra.
Dicho esto, he añadido nuevas funcionalidades.
Ya podemos modificar y borrar usuarios. Para ello usamos un nueva clase JDialog, la cuál para ahorrar tiempo y código, la he escrito de forma que nos va a servir para ambas funcionalidades.
En su constructor incluyo un boolean, y según su valor, el JDialog se construye con la funcionalidad de modificar o con la de borrar.
Para ambas cosas nos va a servir el mismo formulario.
El formulario consiste en un ComboBox para seleccionar un Usuario de los que hay registrados en el Gestor de Usuarios.
Debajo de este combobox tenemos los campos que muestran los atributos del usuario que hayamos seleccionado.
Y debajo un botón de acción
Si estamos en "modo modificar", los campos de texto son editables, excepto el selector de tipo de Usuario.
Para simplificarlo, no vamos a permitir cambiar la clase de un Usuario. Se podría hacer, pero implica eliminar el usuario anterior, crearlo de nuevo bajo la nueva clase seleccionada, transferirles los id's de eventos que tuviera asociados....
No vale la pena complicarse con esto.
Cuando pulsamos el botón en "modo modificar", se recuperan los valores de los campos de texto, se setean en el usuario seleccionado y se le pide al gestor que guarde los cambios en disco.
Cuando estamos en "modo borrar", que recuerdo vamos a usar un boolean para elegir un modo u otro, los campos no son editables. Se muestran los datos del usuario pero no se pueden cambiar.
El botón de acción lo que hará será pedir confirmación antes de borrar, y si se confirma, se elimina el usuario del combobox, luego se elimina del Gestor de Usuarios y se guarda en disco el cambio realizado.
Ambas funcionalidades, la conseguimos con una única clase, que se construirá de un modo u otro según el valor del boolean llamado
"modoBorrar" que se recibe por el constructor.
public class DialogoModificarUsuario extends JDialog{
private boolean modoBorrar; //Indica si este dialogo ha de ser para borrar usuario, y no modificar
private GestorUsuarios gestorUsuarios;
private Font fuentePlana = new Font("Verdana", Font.PLAIN, 20);
private Font fuenteNegrita = new Font("Verdana", Font.PLAIN, 20);
private JTextField campoNombre;
private JTextField campoUser;
private JPasswordField campoPassword1;
private JPasswordField campoPassword2;
private JSpinner campoEdad;
private JComboBox<String> campoTipoUsuario;
private JButton btAccion; //Su accion será distinta según si el dialogo es para borrar o modificar
//Este ComboBox permitirá seleccionar usuarios registrados
private JComboBox<Usuario> comboUsuarios;
//Usuario actualmente seleccionado
private Usuario escogido;
public DialogoModificarUsuario(Frame padre, boolean modal, boolean modoBorrar, GestorUsuarios gestor) {
super(padre, modal);
this.modoBorrar = modoBorrar;
gestorUsuarios = gestor;
iniciarComponentes();
mostrarEscogido();
setLayout(new BorderLayout());
add(new PanelTitulo(), BorderLayout.NORTH);
JPanel pnCentro = new JPanel();
pnCentro.setLayout(new BoxLayout(pnCentro, BoxLayout.Y_AXIS));
pnCentro.add(new PanelSelectorUsuario());
pnCentro.add(new JSeparator(SwingConstants.HORIZONTAL));
pnCentro.add(new PanelDatos());
add(pnCentro, BorderLayout.CENTER);
add(new PanelBoton(), BorderLayout.SOUTH);
setTitle(modoBorrar?"Borrar Usuario":"Modificar Usuario");
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
pack();
setResizable(false);
setLocationRelativeTo(null);
setVisible(true);
}
private void iniciarComponentes() {
campoNombre = new JTextField(10);
campoNombre.setFont(fuentePlana);
campoNombre.setForeground(Color.BLUE);
campoNombre.setEditable(!modoBorrar); //En modo Borrar, no se pueden editar datos
campoUser = new JTextField(10);
campoUser.setFont(fuentePlana);
campoUser.setForeground(Color.BLUE);
campoUser.setEditable(!modoBorrar);
campoPassword1 = new JPasswordField(10);
campoPassword1.setFont(fuentePlana);
campoPassword1.setForeground(Color.BLUE);
campoPassword1.setEditable(!modoBorrar);
campoPassword2 = new JPasswordField(10);
campoPassword2.setFont(fuentePlana);
campoPassword2.setForeground(Color.BLUE);
campoPassword2.setEditable(!modoBorrar);
campoEdad = new JSpinner();
campoEdad.setFont(fuentePlana);
campoEdad.setForeground(Color.BLUE);
campoEdad.setEnabled(!modoBorrar);
SpinnerNumberModel modeloSpinner = new SpinnerNumberModel();
modeloSpinner.setMinimum(18);
modeloSpinner.setValue(20);
campoEdad.setModel(modeloSpinner);
campoTipoUsuario = new JComboBox<String>(new String[] {"Administrador", "DeContenidos", "Limitado"});
campoTipoUsuario.setFont(fuentePlana);
campoTipoUsuario.setForeground(Color.BLUE);
campoTipoUsuario.setBackground(Color.WHITE);
campoTipoUsuario.setEnabled(false); //Siempre desactivado, no se puede modificar el tipo usuario
btAccion = new JButton(modoBorrar?"Borrar Usuario":"Modificar Usuario");
btAccion.setFont(fuenteNegrita);
btAccion.setForeground(Color.BLUE);
if (modoBorrar)
btAccion.addActionListener(new AccionBorrar());
else
btAccion.addActionListener(new AccionModificar());
comboUsuarios = new JComboBox<Usuario>(gestorUsuarios.getArrayUsuarios());
comboUsuarios.setFont(fuenteNegrita);
comboUsuarios.addActionListener(new AccionEscoger());
}
private void mostrarEscogido() {
escogido = (Usuario) comboUsuarios.getSelectedItem();
campoNombre.setText(escogido.getNombre());
campoUser.setText(escogido.getUserName());
campoPassword1.setText(escogido.getPassword());
campoPassword2.setText(escogido.getPassword());
campoEdad.setValue(escogido.getEdad());
if (escogido instanceof Administrador)
campoTipoUsuario.setSelectedIndex(0);
else if (escogido instanceof DeContenidos)
campoTipoUsuario.setSelectedIndex(1);
else
campoTipoUsuario.setSelectedIndex(2);
}
private boolean compruebaCampos() {
if (campoNombre.getText().isEmpty() || campoNombre.getText().isBlank()) {
advertencia("El campo Nombre Completo no puede estar vacío");
return false;
}
if (campoUser.getText().isEmpty() || campoUser.getText().isBlank()) {
advertencia("El campo Nombre Usuario no puede estar vacío");
return false;
}
if (campoPassword1.getPassword().length == 0) {
advertencia("El campo Contraseña no puede estar vacío");
return false;
}
if (campoPassword2.getPassword().length == 0) {
advertencia("El campo Confirmar Contraseña no puede estar vacío");
return false;
}
return true; //Todo OK
}
private void advertencia(String texto) {
JOptionPane.showMessageDialog(this, texto, "Crear Usuario", JOptionPane.WARNING_MESSAGE);
}
private class PanelTitulo extends JPanel {
public PanelTitulo() {
JLabel titulo = new JLabel(modoBorrar?"Eliminar Usuario":"Modificar Usuario");
titulo.setFont(new Font("Verdana", Font.ITALIC, 32));
JPanel pnBienvenido = new JPanel();
pnBienvenido.add(titulo);
pnBienvenido.setBorder(BorderFactory.createLoweredSoftBevelBorder());
add(pnBienvenido);
}
}
private class PanelSelectorUsuario extends JPanel {
public PanelSelectorUsuario() {
add(comboUsuarios);
TitledBorder bordeTitulo = new TitledBorder("Escoja Usuario");
bordeTitulo.setTitleFont(fuentePlana);
setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20),
bordeTitulo));
}
}
private class PanelDatos extends JPanel {
public PanelDatos() {
setLayout(new GridLayout(3, 2, 4, 4));
add(new PanelConEtiqueta("Nombre Completo: ", campoNombre, FlowLayout.RIGHT));
add(new PanelConEtiqueta("Nombre Usuario: ", campoUser, FlowLayout.RIGHT));
add(new PanelConEtiqueta("Indique contraseña: ", campoPassword1, FlowLayout.RIGHT));
add(new PanelConEtiqueta("Repita contraseña: ", campoPassword2, FlowLayout.RIGHT));
add(new PanelConEtiqueta("Edad: ", campoEdad, FlowLayout.CENTER));
add(new PanelConEtiqueta("Tipo de Usuario: ", campoTipoUsuario, FlowLayout.CENTER));
setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
}
}
private class PanelBoton extends JPanel {
public PanelBoton() {
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(new JSeparator(SwingConstants.HORIZONTAL));
JPanel pnBoton = new JPanel();
pnBoton.add(btAccion);
pnBoton.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
add(pnBoton);
}
}
private class PanelConEtiqueta extends JPanel {
public PanelConEtiqueta(String textoEtiq, JComponent componente, int flotar) {
JLabel etiqueta = new JLabel(textoEtiq);
etiqueta.setFont(fuenteNegrita);
setLayout(new FlowLayout(flotar));
add(etiqueta);
add(componente);
}
}
private class AccionEscoger implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
mostrarEscogido();
}
}
private class AccionModificar implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (compruebaCampos()) {
String nombreComp = campoNombre.getText();
String nombreUser = campoUser.getText();
String password = String.valueOf(campoPassword1.getPassword());
String password2 = String.valueOf(campoPassword2.getPassword());
int edad = (int) campoEdad.getValue();
if (password.equals(password2)) {
escogido.setNombre(nombreComp);
escogido.setUserName(nombreUser);
escogido.setEdad(edad);
escogido.setPassword(password);
gestorUsuarios.guardarUsuarios();
JOptionPane.showMessageDialog(null, "Usuario modificado",
"Modificar Usuario", JOptionPane.INFORMATION_MESSAGE);
}
else
advertencia("Las contraseñas no coinciden");
}
}
}
private class AccionBorrar implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
int respuesta = JOptionPane.showConfirmDialog(null,
"¿Seguro que quiere borrar este Usuario",
"Borrar Usuarios", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION) {
//Eliminamos del Gestor de usuarios
gestorUsuarios.borrarUsuario(escogido);
gestorUsuarios.guardarUsuarios();
//Eliminamos del combobox
comboUsuarios.removeItem(escogido);
}
}
}
}
Fijémonos en el JComboBox de Usuarios. Este combo no va a ser de tipo <String>, es decir, no es que simplemente muestre los nombres.
Es de tipo <Usuario>, es decir, contiene en su interior los objetos Usuario que recibe del Gestor de Usuarios.
Para poder recibirlos de forma fácil, lo que vamos a hacer es añadir un método a la clase
GestorUsuarios que nos construya un array simple con todos los usuarios que hay registrados.
public Usuario[] getArrayUsuarios() {
Usuario[] arrayUsers = new Usuario[usuarios.size()];
for (int i = 0; i < usuarios.size(); i++)
arrayUsers[i] = usuarios.get(i);
return arrayUsers;
}
Gracias a este método, luego podemos construir rápidamente el combobox con esta línea:
comboUsuarios = new JComboBox<Usuario>(gestorUsuarios.getArrayUsuarios());
Sin embargo, esto no es suficiente. El combobox ahora contiene objetos de tipo Usuarios, bien, pero para mostrar en pantalla necesita mostrar un String que represente a cada uno de estos objetos.
Para hacer esto, el combobox va a mostrar lo que le devuelva el método toString() de cada uno de estos objetos. Este método lo heredan TODAS las clases de Java, pero para que funcione bien y lo haga según nuestras necesidades, tenemos que sobreescribirlo.
Así que nos vamos a ir a la clase padre
Usuario y vamos a sobreescribir este método.
Yo he optado por hacer que muestre el nombre completo de la persona y a continuación el nombre de usuario con el que ha elegido registrarse.
@Override
public String toString() {
return nombre + " -- " + userName;
}
¡¡ATENCIÓN!!
Al modificar esta clase, por desgracia, los datos que tuviéramos guardados en disco ya no nos van a servir.
Este es uno de los inconvenientes de guardar datos de forma "serializada". Si alteramos el código de la clase de los objetos que estamos guardando, luego al intentar recuperarlos no sirven porque están creados con el código de clase anterior y se produce una excepción.
Así que tras hacer este cambio en la clase Usuario, lo mejor es borrar el archivo donde estemos guardando los usuarios (yo lo guardo en
C:\JavaTicket\usuarios.dat) y que se genere uno nuevo.
(Continúa en el siguiente post)