Autor Tema: Java con interfaz gráfica crear leer modificar archivo txt programa #codigoJava  (Leído 8547 veces)

Anonimuxx 30167832

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 9
    • Ver Perfil
Hola, ¿cómo puedo modificar un archivo txt en java con interfaz grafica? Por ejemplo nos piden un registro de terminales de buses donde se auto genere la id de la terminal cada vez que se haga un registro lugar de la terminal  y nombre  eso lo guardo  en un archivo txt , pero  no sé como modificarlo usando la id, también  tengo que validar que no se registren más de 2 terminales en el mismo lugar. ¿Alguien me puede ayudar porfavor? Se los agradezco.
« Última modificación: 11 de Enero 2022, 20:24 por Ogramar »

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: ayuda como puedo modificar un archivo txt en java con interfaz
« Respuesta #1 en: 11 de Abril 2021, 01:53 »
Lo primero, es crear una clase Terminal con los tres atributos que mencionas: id, nombre y lugar.
Con sus getter, setters y un método toString() que podemos usar para decidir como queremos que se escriban los datos en el archivo TXT.

Código: [Seleccionar]
public class Terminal {

private String id;
private String lugar;
private String nombre;

public Terminal(String id, String nombre, String lugar) {
this.id = id;
this.lugar = lugar;
this.nombre = nombre;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getLugar() {
return lugar;
}

public void setLugar(String lugar) {
this.lugar = lugar;
}

public String getNombre() {
return nombre;
}

public void setNombre(String nombre) {
this.nombre = nombre;
}

@Override
public String toString() {
return String.format("%s -- %s -- %s", id, lugar, nombre);
}
}

A continuación, una clase que se encargue gestionar las Terminales.
Las coleccionará en un ArrayList y tendrá métodos para registrar y modificar terminales.
Pero también para guardar en archivo TXT, recuperar esa información al iniciar el programa y proporcionar otros datos que necesitará la interfaz gráfica.
Cada método está documentado y tiene comentarios explicando como funciona.

Código: [Seleccionar]
public class RegistroTerminales {

private ArrayList<Terminal> terminales;

public RegistroTerminales() {
terminales = new ArrayList<Terminal>();
recuperarTXT();
}

/**
* Busca una Terminal por ID y la retorna
* @param id String con el ID a buscar
* @return El objeto Terminal asociado al ID
*/
public Terminal getTerminal(String id) {
Terminal buscar = null;
//Buscamos la terminal solicitada por ID
for (Terminal ter: terminales)
if (ter.getId().equals(id))
buscar = ter;
//Retornamos terminal encontrada o null si no existe ese ID
return buscar;
}

/**
* Registra una nueva Terminal, siempre que no hayan otras dos terminales
* en el mismo lugar indicado.<br>Durante el registro se autogenera un ID
* y se retorna.
* @param nombre Nombre de la Terminal
* @param lugar Lugar de la Terminal
* @return Nuevo ID de la Terminal
*/
public String registrarTerminal(String nombre, String lugar) {
String id = null;
//Comprobamos si ya hay dos terminales en el mismo lugar
if (contarLugar(lugar) >= 2)
JOptionPane.showMessageDialog(null, "Ya hay al menos dos terminales en el mismo LUGAR."
+ "\nNo se registrará esta terminal", "Registrar Terminal", JOptionPane.WARNING_MESSAGE);
else {
//Generamos ID
id = String.format("ID%04d", terminales.size());
//Registramos terminal
terminales.add(new Terminal(id, nombre, lugar));
JOptionPane.showMessageDialog(null, "Nueva terminal registrada.",
"Registrar Terminal", JOptionPane.WARNING_MESSAGE);
//Guardamos en disco
guardarTXT();
}
//Retornamos ID, puede ser nulo si se rechazó el registro
return id;
}

/**
* Se modifica la Terminal asociada al ID recibido. Si se intenta modificar
* el lugar, previamente se comprobará si ya existen otras dos terminales el
* ese nuevo lugar, en cuyo caso se rechazará la modificación.
* @param id ID de la Terminal que se quiere modificar.
* @param nombre Nuevo nombre para la Terminal.
* @param lugar Nuevo Lugar para la Terminal.
*/
public void modificarTerminal(String id, String nombre, String lugar) {

Terminal modificar = null;
for (Terminal ter: terminales)
if (ter.getId().equals(id)) {
modificar = ter;
break;
}
if (modificar == null)
//No se ha encontrado terminal por esa ID, es muy improbable que esto ocurra
//pero aún así vamos a contemplar esta posibilidad.
JOptionPane.showMessageDialog(null, "No se ha encontrado la terminal con ID: " + id +
"\nPosible inconsistencia de datos, reinicie la aplicación.",
"Modificar Terminal", JOptionPane.ERROR_MESSAGE);
else {
/*
* Puesto que solo se admiten dos terminales en un mismo lugar, hay que
* comprobar que con la opción modificar no se puedan cambiar los "lugares"
* y superar ese limite de dos terminales x lugar
* Así que vamos a comprobar si se quiere modificar el lugar para comprobar
* si ya hay dos terminales en el nuevo lugar que se quiere establecer
*/
if (modificar.getLugar().equals(lugar)) { //El lugar no cambia, solo se modifica el nombre
modificar.setNombre(nombre);
JOptionPane.showMessageDialog(null, "Terminal modificada",
"Modificar Terminal", JOptionPane.INFORMATION_MESSAGE);
guardarTXT();
}
else {//El lugar SI cambia, solo lo admitimos si no existen ya dos terminales en el nuevo lugar
if (contarLugar(lugar) >= 2)
JOptionPane.showMessageDialog(null, "Ya hay al menos dos terminales en el mismo LUGAR."
+ "\nNo se modificará esta terminal", "Modificar Terminal", JOptionPane.WARNING_MESSAGE);
else {
modificar.setNombre(nombre);
modificar.setLugar(lugar);
JOptionPane.showMessageDialog(null, "Terminal modificada",
"Modificar Terminal", JOptionPane.INFORMATION_MESSAGE);
guardarTXT();
}
}
}
}

/**
* Hace un recuento de cuántas Terminales comparten lugar.<br>
* Hay un límite de 2 Terminales por lugar, este método ayuda
* a controlar este límite.
* @param lugar Lugar que se va a comprobar cuantas Terminales comparten.
* @return Cantidad de Terminales que comparten el lugar indicado.
*/
private int contarLugar(String lugar) {
int cont = 0;
for (Terminal ter: terminales)
if (ter.getLugar().equals(lugar))
cont++;

return cont;
}

/**
* Crea un array con todos los ID de Terminales registrados.<br>
* Se empleará para inicializar el JComboBox del panel "Modificar"
* para poder seleccionar ID
* @return Array con los ID.
*/
public String[] getIDRegistrados() {
String[] ids = new String[terminales.size()];
for (int c = 0; c < terminales.size(); c++)
ids[c] = terminales.get(c).getId();

return ids;
}

/**
* Lee el archivo TXT que contiene los datos de las Terminales registradas.
*/
private void recuperarTXT() {

try {
BufferedReader br = new BufferedReader(new FileReader("terminales.txt"));
String linea = br.readLine();
while(linea != null) {
String[] datos = linea.split(" -- ");
terminales.add(new Terminal(datos[0], datos[1], datos[2]));
linea = br.readLine();
}
br.close();
JOptionPane.showMessageDialog(null, "Se han recuperado " + terminales.size() +
"  terminales del archivo TXT", "Recuperar TXT", JOptionPane.INFORMATION_MESSAGE);
} catch (FileNotFoundException e) {
JOptionPane.showMessageDialog(null, "No existe archivo terminales.txt",
"Recuperar TXT", JOptionPane.WARNING_MESSAGE);
} catch (IOException e) {
JOptionPane.showMessageDialog(null, "Error accediendo a terminales.txt",
"Recuperar TXT", JOptionPane.WARNING_MESSAGE);
}
}

/**
* Guarda los datos de las Terminales registradas en un archivo TXT.
*/
private void guardarTXT() {

try {
BufferedWriter bw = new BufferedWriter(new FileWriter("terminales.txt", false));
for (Terminal ter: terminales) {
bw.write(ter.toString());
bw.newLine();
}
bw.close();
} catch (IOException e) {
JOptionPane.showMessageDialog(null, "Error accediendo a terminales.txt",
"Guardar TXT", JOptionPane.WARNING_MESSAGE);
}
}

}

Y por último, la interfaz.
Un JFrame, con dos paneles con pestañas para elegir.
Una para crear nuevo Terminal, el otro para modificar las existentes.

Para modificar, se muestran los ID de las terminales existentes mediante un JComboBox y al ir seleccionado se muestran los datos de cada terminal, pudiendo modificar los datos.

Tanto para crear Terminal, como para modificar, se va a tener en cuenta el límite de solo 2 terminales en un mismo lugar.

Código: [Seleccionar]
public final class GestionTerminales extends JFrame{

private RegistroTerminales registro;
private JTextField jtNombreNuevo;
private JTextField jtLugarNuevo;
private JButton botonNuevo;
private JComboBox<String> selectorID;
private JTextField jtNombreModif;
private JTextField jtLugarModif;
private JButton botonModif;

public GestionTerminales() {

registro = new RegistroTerminales();

JTabbedPane paneles = new JTabbedPane();
paneles.addTab("Registrar", new PanelRegistrar());
paneles.addTab("Modificar", new PanelModificar());
paneles.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
getContentPane().add(paneles);

setTitle("Gestion Terminales");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
}

//Paneles de la interfaz gráfica
private final class PanelRegistrar extends JPanel {

public PanelRegistrar() {

jtNombreNuevo = new JTextField(8);
jtLugarNuevo = new JTextField(8);
botonNuevo = new JButton("Registrar");
botonNuevo.addActionListener(new AccionRegistrar());

setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
JPanel pnCampos = new JPanel();
pnCampos.setLayout(new BoxLayout(pnCampos, BoxLayout.Y_AXIS));
pnCampos.add(new PanelLabelCampo("Nombre:", jtNombreNuevo));
pnCampos.add(new PanelLabelCampo("Lugar:", jtLugarNuevo));
pnCampos.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createRaisedSoftBevelBorder(),
BorderFactory.createEmptyBorder(20, 20, 20, 20)));
add(pnCampos);
add(new JSeparator());
JPanel pnBoton = new JPanel();
pnBoton.add(botonNuevo);
add(pnBoton);
setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
}
}

private final class PanelModificar extends JPanel {

public PanelModificar() {
selectorID = new JComboBox<String>(registro.getIDRegistrados());
selectorID.addActionListener(new AccionSeleccionarID());
jtNombreModif = new JTextField(8);
jtLugarModif = new JTextField(8);
botonModif = new JButton("Modificar");
botonModif.addActionListener(new AccionModificar());
//Si comenzamos sin terminales para modificar, desactivamos controles de este panel
if (selectorID.getItemCount() == 0) {
selectorID.setEnabled(false);
jtNombreModif.setEnabled(false);
jtLugarModif.setEnabled(false);
botonModif.setEnabled(false);
}
else //Sí hay terminales, seleccionamos la primera
selectorID.setSelectedIndex(0);

setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
JPanel pnCampos = new JPanel();
pnCampos.setLayout(new BoxLayout(pnCampos, BoxLayout.Y_AXIS));
pnCampos.add(new PanelLabelCampo("Seleccione ID:", selectorID));
pnCampos.add(new PanelLabelCampo("Nombre:", jtNombreModif));
pnCampos.add(new PanelLabelCampo("Lugar:", jtLugarModif));
pnCampos.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createRaisedSoftBevelBorder(),
BorderFactory.createEmptyBorder(20, 20, 20, 20)));
add(pnCampos);
add(new JSeparator());
JPanel pnBoton = new JPanel();
pnBoton.add(botonModif);
add(pnBoton);
setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
}
}

private final class PanelLabelCampo extends JPanel {

public PanelLabelCampo(String textoLabel, JComponent campo) {
add(new JLabel(textoLabel));
add(campo);
setBorder(BorderFactory.createEmptyBorder(10, 30, 10, 30));
}
}

//Listener de botones y combobox
private final class AccionRegistrar implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
//Recuperamos datos
String nombre = jtNombreNuevo.getText();
String lugar = jtLugarNuevo.getText();
//Comprobamos que no estan vacíos
if (nombre.isBlank())
JOptionPane.showMessageDialog(null, "Campo nombre no puede estar vacío",
"Registrar Terminal", JOptionPane.WARNING_MESSAGE);
else if (lugar.isBlank())
JOptionPane.showMessageDialog(null, "Campo lugar no puede estar vacío",
"Registrar Terminal", JOptionPane.WARNING_MESSAGE);
else {
//Registramos y obtenemos el ID autogenerado
String id = registro.registrarTerminal(nombre, lugar);
if (id != null) {//Registro aprobado
//Limpiamos formulario
jtNombreNuevo.setText(null);
jtLugarNuevo.setText(null);
//Actualizamos comboBox
selectorID.addItem(id);
//Comprobamos si es necesario activar los controles de panel Modificar
if (!selectorID.isEnabled()) {
selectorID.setEnabled(true);
jtNombreModif.setEnabled(true);
jtLugarModif.setEnabled(true);
botonModif.setEnabled(true);
}
}

}

}
}

private final class AccionModificar implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
//Recuperamos datos
String id = (String) selectorID.getSelectedItem();
String nombre = jtNombreModif.getText();
String lugar = jtLugarModif.getText();
//Comprobamos que no estan vacíos
if (nombre.isBlank())
JOptionPane.showMessageDialog(null, "Campo nombre no puede estar vacío",
"Modificar Terminal", JOptionPane.WARNING_MESSAGE);
else if (lugar.isBlank())
JOptionPane.showMessageDialog(null, "Campo lugar no puede estar vacío",
"Modificar Terminal", JOptionPane.WARNING_MESSAGE);
else
registro.modificarTerminal(id, nombre, lugar);

}
}

private final class AccionSeleccionarID implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String id = (String) selectorID.getSelectedItem();
Terminal ter = registro.getTerminal(id);
jtNombreModif.setText(ter.getNombre());
jtLugarModif.setText(ter.getLugar());
}
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new GestionTerminales();
}
});
}

}
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Anonimuxx 30167832

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 9
    • Ver Perfil
Re: ayuda como puedo modificar un archivo txt en java con interfaz
« Respuesta #2 en: 14 de Abril 2021, 04:52 »
Hola muchas gracias por tu ayuda, pero ahora tengo un inconveniente tengo que asignar una terminal a una ruta. 

El sistema de manera automática (es decir, no se escoge en interfaz, sino que
un algoritmo en el código realiza el proceso) deberá asignar la terminal, y, por
ende, se asigna una de las dos posibles unidades que están asociadas a esa terminal. Recuerde que estos podrían no estar disponibles, en caso de que
suceda esto la ruta no podrá crearse
.


es algo así Bueno  También e creado lo de mantenimiento de rutas, de unidades y tengo que ingresar en la ruta Origen y destino, Fecha de salida y llegada, hora de salida y llegada
 esto lo estaba mostrando en un jtable una ves agregados

En mantenimiento de unidades se autogenera una placa  y se carga en un jCombobox el nombre de la terminal creada anteriormente   todo  es con CRUD, y con base a todo lo mencionado el sistema tiene que asignar automáticamente una terminal cuando ya Todo este registrado

y lo e estado haciendo pero no con objetos sino todo en el frame pero el proyecto pide que  todo sea por capas y aun estoy un poco perdido en eso

ayuda porfavor.  gracias...

Anonimuxx 30167832

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 9
    • Ver Perfil
Re: ayuda como puedo modificar un archivo txt en java con interfaz
« Respuesta #3 en: 14 de Abril 2021, 06:27 »
Kabuto también te quiero preguntar como funciona lo del frame es que lo intente con el jtabbed pane y agregando 2 paneles y le coloque el nombre Registrar y modificar pero no me funciona solo me sale el jOpanel diciendo que no existe el archivo

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: ayuda como puedo modificar un archivo txt en java con interfaz
« Respuesta #4 en: 14 de Abril 2021, 12:09 »
¿Qué es una unidad?¿Tiene atributos?
¿Qué es una ruta?¿Tiene atributos?
¿Cómo se supone que son las relaciones entre Unidades, Terminales y Rutas?
¿Una Ruta se compone de dos Terminales?
Para decidir cómo asignar Terminal a un Ruta, ¿depende de que compartan el atributo "lugar"?
¿Las Rutas son siempre dentro de un mismo "lugar"? ¿O una Ruta puede ir de un "lugar" a otro distinto?

Si es posible, estaría bien que compartieses el enunciado completo, para entender mejor lo que se pide modelar.

Kabuto también te quiero preguntar como funciona lo del frame es que lo intente con el jtabbed pane y agregando 2 paneles y le coloque el nombre Registrar y modificar pero no me funciona solo me sale el jOpanel diciendo que no existe el archivo

En el código que escribí, la primera vez que se inicia el programa SIEMPRE aparecerá el aviso de que no existe el archivo txt, porque aún no se han creado datos.

Después de crear datos, en las próximas sesiones sale un aviso similar indicando cuantas Terminales se han recuperado del archivo txt.

Al aceptar estos avisos, debería aparecer el marco JFrame con las dos pestañas para ir a un panel o a otro.



Si no ves este marco, comprueba que no se haya quedado "detrás" de tu editor de código.
Pulsa las teclas Alt+Tab a ver si así aparece.
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Anonimuxx 30167832

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 9
    • Ver Perfil
Re: ayuda como puedo modificar un archivo txt en java con interfaz
« Respuesta #5 en: 14 de Abril 2021, 21:25 »
 Hola kabuto a continuación te paso el enunciado,  tratare de escribirlo todo pero hay algunas imágenes de referencia, en todo caso te coloco un link para que lo veas mejor:

https://drive.google.com/file/d/1_WM6vL4aNPrBO4Y0W1QIqibWjYMHW1Zw/view?usp=sharing

rutas son los destinos , y unidades son los buses

este es el enunciado

Sección del administrador.
En esta sección se describen los procesos que pueden ser vistos y gestionados
únicamente por el administrador; los usuarios de tipo pasajero no pueden ingresar
a ninguna de estas opciones del sistema.
Login.
• Debe existir un archivo para almacenar todos los usuarios del sistema; en este
archivo, estará el administrador previamente creado, es decir, no se registra en
el sistema.
• Para iniciar sesión (login) el usuario indicará su cédula y contraseña, el sistema
deberá detectar de manera automática si se trata de un administrador o un
pasajero; esto porque, tanto el administrador como cada pasajero que se registra
se encuentran en el mismo archivo.
• En la interfaz, la contraseña debe estar encriptada, esto aplica para todos los
usuarios del sistema.
• El sistema no debe permitir ingresar a otra pantalla del sistema si no se ha hecho
inicio de sesión.
• El sistema debe permitir cerrar sesión para poder cambiar de usuarios en el
sistema.
Lugares (estructura de datos)
• Por defecto en el sistema debe estar creada una estructura de datos con los
lugares predeterminados que se utilizarán, los lugares son: San José, Alajuela,
Heredia, Cartago, San Carlos, Puntarenas, Limón.
Menú
• El sistema debe contar con un menú para acceder a las opciones del sistema.
Toda la información se gestiona a través de mantenimientos, lo que se conoce
como un CRUD (Crear, Leer, Modificar, Eliminar).

• Las opciones del menú son los siguientes:
o Mantenimiento de Terminales.
o Mantenimiento de Unidades.
o Mantenimiento de Rutas.
o Reportes.
Mantenimiento de Terminales
• Debe considerar que, si una terminal ya está asignada a una ruta, ésta no se
puede modificar y/o eliminar.
• Cada lugar solo puede tener un máximo de dos terminales.
• Debe crear un archivo donde se almacena la siguiente información:

Campo         Descripción      Componente   Restricción

Identificador              Id de la terminal.                                    Debe ser autogenerado.
Nombre                   Nombre de la terminal.       TextField           

         
Lugar                      Nombre del lugar donde      ComboBox          Se carga la lista de
                                   está la terminal                                       lugares desde el
                                                                                                 código

Número de                Número de la terminal de     ComboBox               Solo existe                                                                                               terminal                    salida del bus.                                                  terminal 1 y 2

Mantenimiento de Unidades
• Debe considerar que, si una unidad ya está asignada a una ruta, ésta no se
puede modificar y/o eliminar.
• Cada unidad solo puede estar asignada a una única terminal, por lo tanto, cada
terminal puede tener un máximo de dos unidades asignadas.
• De acuerdo con lo anterior, debe controlar la cantidad de unidades que se han
asignado a cada terminal.
• Debe crear un archivo donde se almacena la siguiente información:

Campo    Descripción   Componente       Restricción

Placa                  Placa de la unidad.                                     Debe ser autogenerado.
                                                                                          Además, construida por
                                                                                          3 letras (no pueden ser
                                                                                           vocales) y 3 números;
                                                                                            ejemplo: BQT145.

Capacidad             Capacidad de campos         Spinner             Debe limitarse de 0 a 36
                            en la unidad.                                              campos

Nombre de           Se asigna el nombre de       ComboBox          Se carga la lista de
la terminal           la terminal a la que                                       nombres desde el
                          pertenece                                                     archivo de las
                                                                                             terminales que han sido
                                                                                             registradas.

Mantenimiento de Rutas
En esta sección convergen todos los datos suministrados anteriormente; lo cual,
utilizando interfaz gráfica se van a crear las rutas en el sistema. La creación de una
nueva ruta requiere de las siguientes acciones:
• Debe considerar que, si una ruta ya tiene compra de boletos por los usuarios,
ésta no se puede modificar y/o eliminar.
• Para efectos del proyecto solo se van a considerar rutas de ida, es decir, que un
pasajero se desplaza de un lugar X a un lugar Y, sin devolverse.
• Para que se creen las rutas, el administrador debe indicar los siguientes datos:
lugar de origen (salida de la unidad), lugar de destino (llegada de la unidad), el
precio del viaje, la fecha y hora de salida, la fecha y hora de llegada

Campo    Descripción   Componente       Restricción

Origen                Lista de lugares.           ComboBox               Se carga la lista de
                                                                                          lugares desde el código

Destino              Lista de lugares             ComboBox                Se carga la lista de
                                                                                           lugares desde el código

Precio                 Precio del viaje             TextField

Fecha y              Fecha y hora para la      DateChooser            Deben ser componentes
hora                   salida y llegada                                           por aparte, uno para
                                                                                           salida y otro para llegada.


• Debe hacer validaciones como por ejemplo que no se elija el mismo lugar de
salida como de llegada, además, que la fecha de llegada sea mayor a la fecha
de salida, entre otros.
• El sistema de manera automática (es decir, no se escoge en interfaz, sino que
un algoritmo en el código realiza el proceso) deberá asignar la terminal, y, por
ende, se asigna una de las dos posibles unidades que están asociadas a esa
terminal. Recuerde que estos podrían no estar disponibles, en caso de que
suceda esto la ruta no podrá crearse.
• Además, con base a las fechas que se seleccionaron (salida y llegada) debe
calcular la duración en horas y minutos del viaje.
• Una vez realizadas las acciones anteriores, se debe almacenar la información
en el archivo de rutas; los datos que se registran son los siguientes:

Campo                                           Descripción

Identificador                                             Id de la ruta

Id de la terminal                                       Id de la terminal

Placa                                                        Placa de la unidad.

Precio                                                       Precio del viaje.

Fecha y hora salida                                    Fecha y hora de salida del viaje

Origen                                                      Nombre del lugar de salida del viaje.

Fecha y hora llegada                                  Fecha y hora de llegada del viaje.

Destino                                                     Nombre del lugar de llegada del viaje.

Duración                                                   Duración en horas y minutos del viaje.



Sección del pasajero

Registro y login.

• Para registrarse el usuario debe colocar el número de cédula, nombre, correo
electrónico, fecha de nacimiento, género y contraseña. Recuerde que estos
datos se almacenan en el mismo archivo donde esta quemado el administrador.
• Para iniciar sesión (login) el usuario indicará su número de cédula y contraseña.
Recuerde que se utiliza la misma pantalla de inicio de sesión que se indicó en la
sección del administrador.
• Debe permitir cerrar sesión

Campo    Descripción   Componente       Restricción

Cédula(ID)        Cédula del pasajero.     TextField

Nombre             Nombre del pasajero     TextField 

Fecha de            Fecha de nacimiento   DateChooser
nacimiento         del  pasajero

Edad                  Edad del pasajero.       TextField (no            Se calcula a través de la
                                                           editable)                   fecha de nacimiento

Email                Correo electrónico del     TextField                  Debe ser un correo
                         pasajero                                                      electrónico válido.

Género               Género del pasajero.      RadioButton


Contraseña        Contraseña de acceso        Password             Debe estar encriptada
                        del pasajero                                                en la interfaz .


Búsqueda de rutas

• El pasajero tendrá la posibilidad de buscar una ruta de ida.
• Debe solamente colocar el nombre de los lugares de origen y destino, además,
la fecha de salida. Para los lugares utilice el componente ComboBox y cargue
los lugares desde el código; y, para la fecha utilice el componente DateChooser.
• Ahora, el sistema debe ser capaz de realizar las siguientes acciones:
o Buscar las rutas directas de acuerdo con los datos suministrados por el
usuario; es decir, donde el origen, destino y fecha de salida coincidan.
o Es importante considerar que, un viaje podría no ser precisamente
directo, cabe la posibilidad que el pasajero llegue a su destino pasando
por un lugar intermedio. Por ejemplo: asuma que las siguientes rutas
fueron creadas: San Carlos – San José, Puntarenas – San José y San
Carlos – Puntarenas; por su parte, el pasajero quiere viajar de San Carlos
hacia San José, entonces para el caso anterior, el sistema detecta que
hay dos posibles rutas que le puede ofrecer al pasajero, una es de manera
directa, y la otra es pasando por Puntarenas como lugar intermedio, lo
cual, ambas podrían ser válidas.
o Por su parte, para que una ruta con un lugar intermedio sea válida, se
debe cumplir con los siguientes criterios:
▪ La terminal del lugar de origen debe ser igual a la terminal del lugar
intermedio, por ejemplo: la ruta San Carlos – Puntarenas sale de
la terminal número 1, y, la ruta Puntarenas – San José también
sale de la terminal número 1.
▪ Validar que la fecha y hora tanto de salida como de llegada entre
las rutas, no se traslapen.
▪ Validar que ambas unidades tienen campos disponibles.
▪ Para efectos prácticos, solo se contemplará un lugar intermedio.
• El costo del viaje será calculado con la suma de todos los precios de las rutas,
debe considerar si hay o no lugares intermedios.
• El tiempo de viaje será calculado sumando la duración, considerando si existe o
no un lugar intermedio.
• Una vez realizado todos los puntos anteriores, debe mostrar en un Table al
usuario la lista de rutas disponibles para que pueda elegir uno; debe imprimir:
nombre de lugar de origen, nombre de lugar intermedio (si hay), nombre de lugar
de destino, fecha y hora de salida (origen), fecha y hora de llegada (destino),
duración total del viaje, precio total del viaje.

Compra de boletos y asignación de asientos

• El usuario selecciona de la lista la ruta que le convenga.
• Adicional, el usuario debe indicar cuántas personas viajan con él (para efectos
prácticos no puede ser más de 5 personas). Utilice un Spinner para esta acción.
• Si el pasajero que está comprando boletos tiene 65 o más años, se considera
como un adulto mayor, por lo tanto, se le hace un descuento del 50% del total
del precio del viaje.
• Una vez elegida la ruta e indicando la cantidad de personas que viajan, el
sistema automáticamente hace la asignación de los asientos y muestra en la
pantalla el resultado, respetando las siguientes condiciones:
o Al estar el mundo en tiempo de pandemia, la columna del centro de cada
ala (B y E respectivamente) siempre estará deshabilitada, es decir el
sistema no puede asignar personas en esos campos. Ver ejemplo en las
filas 1 y 2.
o La única manera en que la columna del centro de una o ambas alas pueda
estar habilitada es que las personas que viajan sean de una misma
familia. Ver ejemplo en la fila 3, suponiendo que dos parejas distintas han
ingresado al sistema y compran boletos cada uno por su cuenta. Otro
ejemplo, suponiendo que viaja una familia de 5 personas, podrían
acomodarse ya sea como esta en la fila 4 o como se representa en las
filas 5 y 6.
o Además, debe validar el cupo máximo de la unidad, en donde solo estarán
disponibles esas 6 filas por cada ala; por lo cual, debe llevar el control de
los asientos que ya están asignados




Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: ayuda como puedo modificar un archivo txt en java con interfaz
« Respuesta #6 en: 16 de Abril 2021, 02:21 »
Veo que es una práctica bastante extensa.
Necesariamente habrá que usar clases y objetos.

No se cuánto tendrás avanzado. Yo voy a intentar empezarlo desde cero, según como lo haría yo, y a ver hasta donde llego.

De momento empezaría con la parte del login de usuario. Se puede hacer que el JFrame principal utilice un panel con un CardLayout. Este layout permite incorporar muchos paneles en uno solo, de manera que solo se muestre el que nos interese en cada momento.

Por ejemplo puede comenzar mostrando el formulario de login. Cuando el usuario acceda, si es un Administrador pues pasará a mostrar el menú de opciones de administración.
Y si es un Pasajero, pues pasará a mostrar su menú correspondiente.

Pero lo primero será crear las clases correspondientes a los usuarios.
Podemos hacer una clase Usuario, que sería abstracta, de la cuál luego heredarían Administrador y Pasajero.
Tendría solo los dos atributos de Cedula y Password, ya que son comunes a ambos tipos de Usuario.

También podemos sobreescribir  el método equals() para indicar que dos Usuarios se han de considerar "el mismo" si tienen la misma cédula.
Esto luego puede ser útil para evitar que se puedan registrar Usuarios con la misma cédula.

Código: [Seleccionar]
package usuario;

/**
 * Clase abstracta para modelar un Usuario.<br>
 * De esta clase heredarán Administrador y Pasajero.<br>
 * Los atributos mínimos para crear un usuario son la cédula
 * y la contraseña.
 */
public abstract class Usuario {

protected String cedula;
protected String password;

public Usuario(String cedula, String password) {
this.cedula = cedula;
this.password = password;
}

public String getCedula() {
return cedula;
}

public void setCedula(String cedula) {
this.cedula = cedula;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

/**
* Dos Usuarios son iguales si tienen
* la misma cédula.
*/
@Override
public boolean equals(Object objeto) {
if (objeto instanceof Usuario) {
Usuario otroUsu = (Usuario) objeto;
return cedula.equals(otroUsu.cedula);
}
else
return false;
}
}

Luego tendríamos la clase Administrador.
Esta clase en principio parece que no incorpora atributos extra: ni nombre, ni email, ni nada...

Sí le vamos a sobreescribir el método toString() para determinar como queremos representar los objetos Administrador en una línea de texto.
Esto será útil de cara a cuando haya que guardar los Usuarios en un archivo txt.
Según el enunciado, Administradores y Pasajeros se guardarán juntos en un mismo archivo.
Para poder distinguir unos de otros, podemos crear una regla identificativa. Yo por ejemplo, he optado por hacer que las líneas correspondientes a los usuarios Administradores, comiencen con una A mayúscula.
Cada dato se escribirá separado de dos guiones con espacios a los lados " -- ". Esto luego permitirá separar fácilmente unos datos de otros para cuando queramos recuperar los usuarios guardados en el txt y volver a registrarlos en el sistema.
Código: [Seleccionar]
package usuario;

/**
 * Clase para modelar un Administrador.<br>
 * No requiere de ningún atributo extra a parte de los
 * heredados de Usuario.<br>Sí se sobreescribe el método
 * <i>toString()</i> para indicar como vamos a querer
 * que se guarden sus datos en una línea del archivo txt.
 */
public final class Administrador extends Usuario {

public Administrador(String cedula, String password) {
super(cedula, password);
}

/**
* Devuelve los valores de los atributos con la letra A inicial
* para identificar al Usuario como un Administrador a la hora de
* recuperar los datos del archivo txt.
*/
@Override
public String toString() {
return String.format("A -- %s -- %s", cedula, password);
}

}

Ahora la clase Pasajero.
Esta clase si tendrá más atributos: nombre, email, genero, fecha nacimiento.
Todos los atributos serán String, excepto la fecha de nacimiento, que será de tipo Date..., al menos de momento.

Digo de momento, porque la clase Date no me gusta usarla debido a que se considera prácticamente obsoleta (deprecated). Esta clase tiene una serie de carencias que fueron solucionadas con clases como LocalDate y LocalTime, que son las que deberían usarse.

Sin embargo, el enunciado exige usar para la interfaz gráfica la librería externa JDateChooser, y por lo que he visto en su documentación, las fechas las trabaja con la clase Date. Así que parece que no quedará más remedio que usar estas clases.

Los objetos Pasajero, cuando se guarden en archivo de texto, se identificarán con una P mayúscula al principio de la línea.
Por cierto, para guardar la fecha en el archivo de texto, puesto que no es un String (es un Date), hay que decidir como hacerlo.
Se podría agregar código para transformar la fecha en un String tipo "dd-mm-aaaa", pero también es posible representar la fecha con un valor numérico de tipo long. Así que para ahorrar código probaremos a usar este valor.
Si luego vemos que no nos funciona bien, pues ya buscaremos otra forma de hacerlo.

Código: [Seleccionar]
package usuario;

import java.util.Date;

/**
 * Clase para modelar un Pasajero.<br>
 * incluye todos los atributos requeridos para construir un Pasajero.<br>
 * Sobreescribe el método <i>toString()</i> para indicar como vamos a querer
 * que se guarden sus datos en una línea del archivo txt.
 */
public final class Pasajero extends Usuario{

private String nombre;
private Date fechaNac;
private String genero;
private String eMail;

public Pasajero(String cedula, String password, String nombre,
Date fechaNac, String genero, String eMail) {
super(cedula, password);
this.nombre = nombre;
this.fechaNac = fechaNac;
this.genero = genero;
this.eMail = eMail;
}

public String getNombre() {
return nombre;
}

public void setNombre(String nombre) {
this.nombre = nombre;
}

public Date getFechaNac() {
return fechaNac;
}

public void setFechaNac(Date fechaNac) {
this.fechaNac = fechaNac;
}

public String getGenero() {
return genero;
}

public void setGenero(String genero) {
this.genero = genero;
}

public String geteMail() {
return eMail;
}

public void seteMail(String eMail) {
this.eMail = eMail;
}

/**
* Devuelve los valores de los atributos con la letra P inicial
* para identificar al Usuario como un Pasajero a la hora de
* recuperar los datos del archivo txt.<br>
* La fecha, un objeto Date, se guarda como milisegundos.
*/
@Override
public String toString() {
return String.format("P -- %s -- %s -- %s -- %d -- %s -- %s",
cedula, password, nombre, fechaNac.getTime(), genero, eMail);
}

}


Bien, tenemos clases que representan los distintos Usuario. Ahora hace falta una clase que los gestione, que tenga un ArrayList, que añada nuevos usuarios, que los busque para validar un login, que los guarde en un archivo txt, que los lea de ese archivo, etc...

He escrito la siguiente clase, que no está terminada, pues irá creciendo en código según avance con el programa.
De momento tiene métodos para leer archivo de texto, escribirlo en disco, y validar un login.
Le faltará por ejemplo un método para registrar nuevo usuario.

Código: [Seleccionar]
package usuario;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;

import javax.swing.JOptionPane;

/**
 * Esta clase gestionará un ArrayList con los Usuarios del sistema.<br>
 * Se encargará de registrar usuarios, comprobar datos para login,
 * guardar y leer el archivo txt con la información de los Usuarios.
 */
public final class GestorUsuario {

private ArrayList<Usuario> usuarios;

public GestorUsuario() {
usuarios = new ArrayList<Usuario>();
cargarDatos();
}

public Usuario login(String cedula, String password) {
//Buscará un usuario que coincida cedula y password, y lo retornará
for (Usuario usu: usuarios) {
if (usu.getCedula().equals(cedula) && usu.getPassword().equals(password))
return usu;
}
//Si bucle for no ha retornado ningun usuario, es que el login no es válido
return null;
}

/**
* Leerá el archivo de datos de Usuarios.<br>
* En caso de no existir archivo, o fracasar la lectura,
* creará automáticamente un usuario Administrador por defecto.
*/
private void cargarDatos() {

try {
BufferedReader br = new BufferedReader(new FileReader("usuarios.txt"));
String linea = br.readLine();

while(linea != null) {

//Separamos datos contenidos en la linea
String[] datos = linea.split(" -- ");

if (datos[0].equals("A")) {//Este usuario es un Administrador
//Administrador solo tiene cedula y password
usuarios.add(new Administrador(datos[1], datos[2]));
} else if (datos[0].equals("P")) { //Pasajero
//La fecha nacim. esta guardada en milisegundos,
//hay que generar un Date con ellos.
long milis = Long.parseLong(datos[4]);
Date fechaNac = new Date(milis);
usuarios.add(new Pasajero(datos[1], datos[2], datos[3], fechaNac, datos[5], datos[6]));
}

//siguiente linea
linea = br.readLine();
}

br.close();

} catch (FileNotFoundException e) {
JOptionPane.showMessageDialog(null, "No se encuentra archivo: usuarios.txt\n"
+ "Se intentará generar uno nuevo", "Cargar Datos Usuarios",
JOptionPane.WARNING_MESSAGE);
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, "Error intentando leer: usuarios.txt",
"Cargar Datos Usuarios", JOptionPane.WARNING_MESSAGE);
} catch (Exception error) {
JOptionPane.showMessageDialog(null, "Error recuperando datos de: usuarios.txt\n"
+ "Error:\n" + error.getLocalizedMessage(),
"Cargar Datos Usuarios", JOptionPane.WARNING_MESSAGE);
}

//Si fracasa la lectura de Usuarios, creamos nuevo archivo con un admin por defecto
if (usuarios.isEmpty()) {
usuarios.add(new Administrador("CED000", "admin"));
guardarDatos();
}

}

/**
* Guardará los datos de Usuarios en un archivo de texto.
*/
private void guardarDatos() {
try {
BufferedWriter bw = new BufferedWriter(new FileWriter("usuarios.txt", false));
//Por cada usuario, creamos una línea de texto en el archivo
//Será necesario, hacer casting a cada tipo de Usuarios
for (Usuario usu: usuarios) {
if (usu instanceof Administrador)
bw.write(((Administrador)(usu)).toString());
else
bw.write(((Pasajero)(usu)).toString());

bw.newLine();
}
bw.close();
} catch (IOException e) {
JOptionPane.showMessageDialog(null, "Error intentando guardar: usuarios.txt",
"Guardar Datos Usuarios", JOptionPane.WARNING_MESSAGE);
}
}
}
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: ayuda como puedo modificar un archivo txt en java con interfaz
« Respuesta #7 en: 16 de Abril 2021, 02:47 »
Vamos a comenzar a hacer la interfaz.

El primer panel que mostraremos, sería una pantalla de login.
Pediremos cedula y password.
Podemos usar un JCheckBox para que el usuario indique si lo que quiere es crear un nuevo registro.
Tendrá un método para recoger los valores que introduzca el usuario en los dos campos de texto y retornarlos juntos.
Para que vayan juntos, se agruparán en un array de String.
Es necesario retornarlos porque no será aquí donde se comprueben si corresponden a un usuario registrado, esto se hará en la clase Main, que ya veremos después.

Otro método es para saber si el usuario quiere hacer registro nuevo y otro más para asignarle un ActionListener al botón. Este ActionListener se escribirá en la clase Main, donde se tendrá mejor acceso a la clase que gestiona usuarios y a los otros paneles de la interfaz.

Código: [Seleccionar]
package gui;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

@SuppressWarnings("serial")
public class PanelLogin extends JPanel{

private JTextField jtCedula;
private JPasswordField jtPassword;
private JCheckBox jcNuevoRegistro;
private JButton btLogin;

public PanelLogin() {
jtCedula = new JTextField(8);
jtPassword = new JPasswordField(8);
jcNuevoRegistro = new JCheckBox("Nuevo Registro");
jcNuevoRegistro.setToolTipText("Marque esta casilla para registrar un nuevo usuario");
btLogin = new JButton("Iniciar Sesión");

setLayout(new BorderLayout());
add(new PanelCentral(), BorderLayout.CENTER);
add(new PanelSur(), BorderLayout.SOUTH);

setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
}

private class PanelCentral extends JPanel {

public PanelCentral() {

JLabel texto = new JLabel("Introduzca datos para iniciar sesión");
texto.setFont(new Font("Verdana", Font.BOLD, 24));
JPanel pnTexto = new JPanel();
pnTexto.add(texto);

JPanel pnNombre = new JPanel();
pnNombre.add(new PanelCampoTexto("Cédula: ", jtCedula));

JPanel pnPass = new JPanel();
pnPass.add(new PanelCampoTexto("Password: ", jtPassword));

JPanel pnRegistro = new JPanel();
pnRegistro.add(jcNuevoRegistro);

setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(pnTexto); add(pnNombre); add(pnPass); add(pnRegistro);
}
}

private class PanelSur extends JPanel {

public PanelSur() {
JPanel pnBoton = new JPanel();
pnBoton.add(btLogin);
add(pnBoton);
}
}

private class PanelCampoTexto extends JPanel {

public PanelCampoTexto(String texto, JComponent campo) {
setLayout(new FlowLayout(FlowLayout.RIGHT));
add(new JLabel(texto));
add(campo);
}
}

//Métodos
/**
* Retorna los datos del formulario introducidos por el usuario.<br>
* Si algún campo esta vacío, se avisa en pantalla y se retorna null.<br>
* Si ambos campos contienen datos, se retornan juntos en un array.
* @return Array de String[] con el valor de la Cédula y el Password
*/
public String[] getDatos() {
String cedula = jtCedula.getText();
String password = String.valueOf(jtPassword.getPassword());
//Comprobamos si hay datos
if (cedula.isBlank()) {
JOptionPane.showMessageDialog(null, "El campo Cédula no puede estar vacío",
"Login Usuario", JOptionPane.WARNING_MESSAGE);
return null;
} else if (password.isBlank()) {
JOptionPane.showMessageDialog(null, "El campo Password no puede estar vacío",
"Login Usuario", JOptionPane.WARNING_MESSAGE);
return null;
} else {
//Juntamos ambos datos en un array y lo retornamos
return new String[] {cedula, password};
}
}

/**
* Indica si el Usuario está solicitando crear un nuevo registro
* con los datos que ha introducido.<br>El Usuario puede hacer esta
* solicitud marcando el CheckBox correspondiente.
* @return TRUE si es nuevo registro, FALSE en caso contrario.
*/
public boolean esNuevoRegistro() {
return jcNuevoRegistro.isSelected();
}

/**
* Resetea el formulario borrando los valores
* de todos sus campos.
*/
public void resetFormulario() {
jtCedula.setText(null);
jtPassword.setText(null);
jcNuevoRegistro.setSelected(false);
}

/**
* Recibe un ActionListener para agregarlo al botón de accion.<br>
* Este Listener se escribe en la clase Main porque requiere poder
* interactuar con otros objetos como el "Gestor de Usuarios" y
* el "Panel Principal" de la interfaz, que se encuentran fuera
* de este ámbito.
* @param accionBotonLogin ActionListener para el botón de acción
*/
public void setAccionBotonLogin(ActionListener accionBotonLogin) {
btLogin.addActionListener(accionBotonLogin);
}

}

Esto nos daría un panel como este, no es muy bonito, pero bueno. Cuando el programa esté terminado, se puede jugar a trastear con él para darle otra estética menos espartana



Si el login tiene éxito, se ha de mostrar un Panel de Administrador o un Panel de Pasajero, según el tipo de usuario que haya accedido al sistema.

Vamos primero con el panel de administrador.
Se trataría de un menú de 4 opciones, así que podemos usar 4 botones. Podemos mostrarlos con texto grande y hacerlos de gran tamaño, mostrados en una grilla (GridLayout) de 4x4.

Un quinto botón "normal" serviría para cerrar sesión (logout)

Código: [Seleccionar]
package gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class PanelAdmin extends JPanel{

private BotonOpcion btTerminal;
private BotonOpcion btUnidad;
private BotonOpcion btRuta;
private BotonOpcion btReporte;
private JButton btLogout;

public PanelAdmin() {

btTerminal = new BotonOpcion("Gestión<br>de<br>Terminales");
btUnidad = new BotonOpcion("Gestión<br>de<br>Unidades");
btRuta = new BotonOpcion("Gestión<br>de<br>Rutas");
btReporte = new BotonOpcion("Reportes");
btLogout = new JButton("Cerrar Sesión");

setLayout(new BorderLayout());
add(new PanelNorte(), BorderLayout.NORTH);
add(new PanelCentral(), BorderLayout.CENTER);
add(new PanelSur(), BorderLayout.SOUTH);

}

private class PanelNorte extends JPanel {

public PanelNorte() {
JLabel titulo = new JLabel("Panel de Administrador");
titulo.setFont(new Font("Verdana", Font.ITALIC, 36));
add(titulo);
setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(20, 20, 0, 20),
BorderFactory.createRaisedSoftBevelBorder()));
}
}

private class PanelCentral extends JPanel {

public PanelCentral() {

setLayout(new GridLayout(2,2,15,15));
add(btTerminal); add(btUnidad);
add(btRuta); add(btReporte);
setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
}
}

private class PanelSur extends JPanel {

public PanelSur() {
JPanel pnBoton = new JPanel();
pnBoton.add(btLogout);
add(pnBoton);
}
}

private class BotonOpcion extends JButton {

public BotonOpcion(String texto) {
super("<html><p style=\"text-align:center\">" + texto + "</p></html>");
setFont(new Font("Verdana", Font.BOLD, 18));
setFocusPainted(false);
setBackground(new Color(102, 204, 255));
setForeground(Color.WHITE);
setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEtchedBorder(),
BorderFactory.createEmptyBorder(10, 10, 10, 10)));
addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {}
@Override
public void mousePressed(MouseEvent e) {}
@Override
public void mouseReleased(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {
setForeground(new Color(204, 0, 0));
}
@Override
public void mouseExited(MouseEvent e) {
setForeground(Color.WHITE);
}
});
}
}

//Métodos
public void setAccionLogout(ActionListener accion) {
btLogout.addActionListener(accion);
}

}

Se vería algo como esto:


Al cerrar sesión, se volvería de nuevo al panel de login.
Y si se pulsará alguno de los 4 botones del menú, llevaría a otros paneles.
Como dije, todos estos paneles que habrá que ir creando, se pueden agrupar en un "Panel Principal" que use un CardLayout para gestionar todos estos paneles.
Este panel tendría este código.
Código: [Seleccionar]
package gui;

import java.awt.CardLayout;

import javax.swing.JPanel;

@SuppressWarnings("serial")
public class PanelPrincipal extends JPanel{

private CardLayout gestorPaneles;

public PanelPrincipal() {
gestorPaneles = new CardLayout();
setLayout(gestorPaneles);
}

public void mostrarPanel(String nombre) {
gestorPaneles.show(this,  nombre);
}

}
Sí, así de simple. Se le aplica un CardLayout y se le da un método mediante el cuál podamos pedirle que muestre un panel u otro, llamándolos por su "nombre.

Este "Panel Principal", será el contenedor del JFrame que escribiremos en nuestra clase Main.

Esta clase, es donde tendremos el Gestor de Usuarios (y posteriormente un Gestor de Terminales, de Unidades, de Rutas..)
Y tendremos todos los paneles, tendremos los ActionListener para los botones de acción de los paneles... Será la clase que haga de nexo con todo y ponga en marcha el programa.

Un atributo importante que tendrá será un objeto de clase Usuario, para representar el usuario que se haya logueado.
Según si este usuario es Administrador o Pasajero, se mostrarán unas opciones u otras.

De momento tengo este código, que junto a todo lo escrito anteriormente, ya podemos lanzar el programa y probar a loguearnos como Administrador con los datos
Cédula: CED000
Password: admin

Solo se puede iniciar y cerrar sesión, nada más. Lo siguiente que quiero añadir es el poder registrar un nuevo usuario. A ver cuando puedo...
Código: [Seleccionar]
package gui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

import usuario.*;

@SuppressWarnings("serial")
public class Main extends JFrame{

///Uusario que ha logueado, puede ser Admin o Pasajero
private Usuario logueado;

//Gestores
private GestorUsuario usuarios;

//Paneles
private PanelPrincipal pnPrincipal;
private PanelLogin pnLogin;
private PanelAdmin pnAdmin;

public Main() {

usuarios = new GestorUsuario();
pnPrincipal = new PanelPrincipal();
pnLogin = new PanelLogin();
pnLogin.setAccionBotonLogin(new AccionLogin());
pnAdmin = new PanelAdmin();
pnAdmin.setAccionLogout(new AccionLogout());

//Añadimos cada panel al panel principal.
pnPrincipal.add(pnLogin, "login");
pnPrincipal.add(pnAdmin, "admin");

setContentPane(pnPrincipal);

setTitle("Gestion de Terminales");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
}

//Acciones
/**
* Recoge los datos del formulario de login y permite acceder
* a un usuario registrado, o bien crear un nuevo registro.<br>
* Cuando el Usuario ha accedido al sistema, se mostrará un panel
* de opciones según si es Administrador o Pasajero.
*/
private class AccionLogin implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
//Recuperamos datos del formulario login
String[] datosLogin = pnLogin.getDatos();

if (datosLogin !=  null) {
//Preguntamos si es nuevo registro
if (pnLogin.esNuevoRegistro()) {
//TODO: Codigo para crear nuevo registro
}
else {//Es un login normal
//Intentamos login con los datos
logueado = usuarios.login(datosLogin[0], datosLogin[1]);
}

//Comprobamos si ha tenido exito el login y que tipo usuario se trata
if (logueado == null)
JOptionPane.showMessageDialog(null,
"Los datos introducidos no coinciden con ningun Usuario",
"Login Usuario", JOptionPane.WARNING_MESSAGE);
else {
//Login exitoso. Se mostrará un nuevo panel, según tipo usuario
if (logueado instanceof Administrador)
pnPrincipal.mostrarPanel("admin");
else
pnPrincipal.mostrarPanel("pasajero");
//El formulario de login se resetea
pnLogin.resetFormulario();
}
}
}
}

private class AccionLogout implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
logueado = null;
pnPrincipal.mostrarPanel("login");
}
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Main();
}
});
}
}
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Anonimuxx 30167832

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 9
    • Ver Perfil
Re: ayuda como puedo modificar un archivo txt en java con interfaz
« Respuesta #8 en: 16 de Abril 2021, 03:27 »
Hola kabuto, te agradezco mucho apenas voy a probar con tu código yo lo estaba avanzando prácticamente  ya casi terminando  con la parte de administrador pero necesitaba usar objetos y pues  ese tema no lo se manejar muy bien y pues mi profe quiere que lo haga con objetos o de no me califican este proyecto, y pues mi profesor no explica muy bien que digamos.

pero agradezco mucho tu ayuda, ya no me quedan casi días para poder entregarlo y pues todo lo que tenia echo esta malo, funciona pero no  como quiere el profesor que lo hagamos

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: ayuda como puedo modificar un archivo txt en java con interfaz
« Respuesta #9 en: 18 de Abril 2021, 01:11 »
Lamento que andes corto de tiempo. Voy a intentar avanzar y explicar lo que pueda, pero por desgracia mi tiempo libre es muy escaso.

Lo siguiente que quería hacer era poder registrar nuevos Usuarios, que según el enunciado serán Pasajeros necesariamente. Parece ser que no hay opción de registrar administradores, para añadir más admin a parte del que puse en el código, sería escribiendo sus datos directamente en el txt.

Bueno, la forma de hacer un registro es desde la pantalla de login, se introduce cédula y password, y se marca el checkbox para indicar que queremos hacer nuevo registro:


Al pulsar el botón, ha de aparecer un formulario mostrando la cédula y password introducidos, además de otros campos como edad, email, radiobutton para el genero, un selector de fecha de nacimiento(JDateChooser) y un campo edad (no editable) donde la edad se autocalcula según la fecha seleccionada.

Así que toca escribir una nueva clase JPanel para modelar este formulario.
Este es el código que he escrito:
Código: [Seleccionar]
package gui;

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JRadioButton;
import javax.swing.JTextField;

import com.toedter.calendar.JDateChooser;

@SuppressWarnings("serial")
public class PanelFormularioPasajero extends JPanel {

private JTextField jtCedula;
private JPasswordField jtPassword;
private JTextField jtNombre;
private JTextField jtEdad;
private JTextField jtEmail;
private JRadioButton rbHombre;
private JRadioButton rbMujer;
private JDateChooser selecFecha;
private JButton btRegistrar;
private JButton btCancelar;

public PanelFormularioPasajero() {

jtCedula = new JTextField(8);
jtPassword = new JPasswordField(8);
jtNombre = new JTextField(8);
jtEdad = new JTextField(4);
jtEdad.setEditable(false);
jtEmail = new JTextField(8);
rbHombre = new JRadioButton("Hombre");
rbHombre.setSelected(true);
rbMujer = new JRadioButton("Mujer");
ButtonGroup gb = new ButtonGroup();
gb.add(rbHombre); gb.add(rbMujer);
selecFecha = new JDateChooser("dd/MM/yy", "##/##/##", '-');
selecFecha.setDate(new Date()); //Comienza con fecha actual
selecFecha.setMaxSelectableDate(new Date()); //Y Además no se permite fechas posteriores a hoy
btRegistrar = new JButton("Registrar");
btCancelar = new JButton("Cancelar");
btCancelar.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
resetFormulario();
}
});

setLayout(new BorderLayout());
add(new PanelNorte(), BorderLayout.NORTH);
add(new PanelCentro(), BorderLayout.CENTER);
add(new PanelSur(), BorderLayout.SOUTH);

}

private class Panel1 extends JPanel {

public Panel1() {

JPanel pnCedula = new JPanel();
pnCedula.add(new JLabel("Cédula:"));
pnCedula.add(jtCedula);

JPanel pnNombre = new JPanel();
pnNombre.add(new JLabel("Nombre:"));
pnNombre.add(jtNombre);

JPanel pnPassword = new JPanel();
pnPassword.add(new JLabel("Contraseña:"));
pnPassword.add(jtPassword);

setLayout(new GridLayout(1,3));
add(pnCedula); add(pnNombre); add(pnPassword);
}
}

private class Panel2 extends JPanel {

public Panel2() {

JPanel pnEmail = new JPanel();
pnEmail.add(new JLabel("E-Mail:"));
pnEmail.add(jtEmail);

JPanel pnEdad = new JPanel();
pnEdad.add(new JLabel("Edad:"));
pnEdad.add(jtEdad);

JPanel pnGenero = new JPanel();
pnGenero.add(rbHombre);
pnGenero.add(rbMujer);

setLayout(new GridLayout(1,3));
add(pnEmail); add(pnEdad); add(pnGenero);
}
}

private class Panel3 extends JPanel {

public Panel3() {

add(new JLabel("Fecha Nacimiento:"));
add(selecFecha);
}
}

private class PanelNorte extends JPanel {

public PanelNorte() {
JLabel titulo = new JLabel("Registro de nuevo usuario");
titulo.setFont(new Font("Verdana", Font.ITALIC, 36));
add(titulo);
setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(20, 20, 0, 20),
BorderFactory.createRaisedSoftBevelBorder()));
}
}

private class PanelCentro extends JPanel {

public PanelCentro() {

setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(new Panel1()); add(new Panel2()); add(new Panel3());
setBorder(BorderFactory.createEmptyBorder(20, 20, 10, 20));
}
}

private class PanelSur extends JPanel {

public PanelSur() {
JPanel pnRegistrar = new JPanel();
pnRegistrar.add(btRegistrar);
JPanel pnCancelar = new JPanel();
pnCancelar.add(btCancelar);

setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
add(pnRegistrar);
add(pnCancelar);
setBorder(BorderFactory.createEmptyBorder(10, 20, 20, 20));
}
}

//Metodos

/**
* Junta todos los datos en un array y los retorna.<br>
* Puesto que hay datos de distintas clases, String y Date,
* los retornamos como Object.
* @return Array de Object con los datos del formulario.
*/
public Object[] getDatos() {

Object[] datos = new Object[6];
datos[0] = jtCedula.getText();
datos[1] = String.valueOf(jtPassword.getPassword());
datos[2] = jtNombre.getText();
datos[3] = jtEmail.getText();
datos[4] = rbHombre.isSelected()?"Hombre":"Mujer";
datos[5] = selecFecha.getDate();
//La edad no se retorna, pero se calcula para mostrar en formulario
calcularEdad();

return datos;
}

/**
* Borra todos los datos insertados dejando limpio
* el formulario.
*/
public void resetFormulario() {
jtCedula.setText(null);
jtPassword.setText(null);
jtNombre.setText(null);
jtEdad.setText(null);
jtEmail.setText(null);
selecFecha.setDate(new Date());
}

/**
* Setea un valor para la cédula.<br>
* Este valor provendrá del formulario de login, cuando el usuario
* ha solicitado registrarse como nuevo usuario.
* @param cedula Valor String para el campo cédula
*/
public void setCedula(String cedula) {
jtCedula.setText(cedula);
}

/**
* Setea un valor para la contraseña.<br>
* Este valor provendrá del formulario de login, cuando el usuario
* ha solicitado registrarse como nuevo usuario.
* @param pass Valor String para el campo contraseña.
*/
public void setPassword(String pass) {
jtPassword.setText(pass);
}

/**
* Calcula la edad del usuario recuperando la fecha seleccionada en el
* JDateChooser y comparando con la fecha actual.<br>
*/
private void calcularEdad() {
Date selec = selecFecha.getDate();
Date hoy = new Date();

long diferencia = hoy.getTime() - selec.getTime();
//Convertimos a horas
long horas = diferencia/3600000;
//Horas a dias
int dias = (int) (horas/24);
//Y los años serán la edad
int edad = dias/365;
jtEdad.setText(Integer.toString(edad));
}

/**
* Una validación muy simple para comprobar si el valor introducido
* en el campo Email tiene el formato esperado para una dirección de
* correo electrónico.<br>
* La comprobación es muy básica, se limita a ver si hay una arroba y al menos un punto.
* Y que este punto está después de la arroba, con al menos 1 carácter entre ambos.
* @return TRUE si parece un e-mail válido en su formato, FALSE en caso contrario.
*/
public boolean validarEmail() {
String email = jtEmail.getText();

if (email.isBlank())
return false;
else {
int arroba = email.indexOf('@');
int punto = email.lastIndexOf('.');
if (arroba == -1 || punto == -1)
return false;
else
return punto - arroba > 1;
}
}

/*
* Los siguientes métodos son para agregar acciones a los botones
* del formulario. Estas acciones se escriben desde la clase Main
* donde se puede interactuar con otros objetos como paneles y el
* gestor de usuarios, que no son visibles desde esta clase.
*
* El botón Cancelar recibe una segunda acción desde esta misma clase,
* escrita en el constructor, que es simplemente resetear el formulario.
*/
public void setAccionRegistrar(ActionListener accion) {
btRegistrar.addActionListener(accion);
}

public void setAccionCancelar(ActionListener accion) {
btCancelar.addActionListener(accion);
}
}

De él quiero comentar cosas sobre el JDateChooser. Nunca antes lo había usado, ya que es una librería externa "no oficial". Es muy útil sin duda, aunque como ya comenté, está basado en clases casi en desuso como Date y Calendar.
Revisando su documentación, he visto que en su constructor podemos indicarle que formato queremos para mostrar la fecha, así como una "careta" para que el campo de texto que incluye tome el tamaño adecuado.
El tercer argumento, el guión, es para indicar que caracter queremo usar como separador entre dia-mes-año
Código: [Seleccionar]
selecFecha = new JDateChooser("dd/MM/yy", "##/##/##", '-');
Para que el campo de texto del selector no aparezca vacío, le seteo la fecha actual:
Código: [Seleccionar]
selecFecha.setDate(new Date()); //Comienza con fecha actual
El enunciado no dice nada sobre límites de edad para registrar pasajeros, así que en principio se puede registrar alguien nacido hoy mismo, por lo que tendría 0 años....
Sin embargo, si he creído oportuno impedir que se puedan seleccionar fechas posteriores a la actual y esto lo limito con este método:
Código: [Seleccionar]
selecFecha.setMaxSelectableDate(new Date());
Explicado esto, veamos los métodos que va a tener esta clase.
El primero será para recopilar todos los datos del formulario y retornarlos. La idea es recibirlos en la clase Main, desde donde tomaremos decisiones según estos datos.

Código: [Seleccionar]
public Object[] getDatos() {

Object[] datos = new Object[6];
datos[0] = jtCedula.getText();
datos[1] = String.valueOf(jtPassword.getPassword());
datos[2] = jtNombre.getText();
datos[3] = jtEmail.getText();
datos[4] = rbHombre.isSelected()?"Hombre":"Mujer";
datos[5] = selecFecha.getDate();
//La edad no se retorna, pero se calcula para mostrar en formulario
calcularEdad();

return datos;
}

Los datos los juntamos en un array para que vayan todos juntos. Si todos los valores fuesen String, podríamos usar un array de String. Pero hay un dato que no lo es, la fecha de nacimiento (es un Date), así que para que puedan ir todos juntos, usaremos un array de Object.
Esto luego veremos que supone un pequeño inconveniente, para operar con ellos habrá que casting a String y Date según corresponda, pero se compensa por la comodidad de poder enviarlos todos juntos en el mismo array.

Otro método será el típico de resetear formulario, no requiere explicaciones:
Código: [Seleccionar]
public void resetFormulario() {
jtCedula.setText(null);
jtPassword.setText(null);
jtNombre.setText(null);
jtEdad.setText(null);
jtEmail.setText(null);
selecFecha.setDate(new Date());
}

Tendrá dos setter, uno para setear la Cédula y otro para setear el Password. Esto es porque dichos datos serán recuperados desde el formulario de login inicial. Luego el usuario podrá modificarlos si quiere antes de registrar

Código: [Seleccionar]
public void setCedula(String cedula) {
jtCedula.setText(cedula);
}

public void setPassword(String pass) {
jtPassword.setText(pass);
}


Método interesante es el de calcular la edad. Se recupera la fecha seleccionada en el JDateChooser y la actual.
Se calcula la diferencia entre ambas, en milisegundos.... los cuáles para transformar en años, de forma que se entienda lo que se hace, pues primero convierto a horas, luego a días y luego a años.
De este modo, se obtiene la edad del Pasajero. Este dato no es un atributo de la clase Pasajero, pero el enunciado pide que se calcule y se muestre en un campo de texto.

Código: [Seleccionar]
private void calcularEdad() {
Date selec = selecFecha.getDate();
Date hoy = new Date();

long diferencia = hoy.getTime() - selec.getTime();
//Convertimos a horas
long horas = diferencia/3600000;
//Horas a dias
int dias = (int) (horas/24);
//Y los años serán la edad
int edad = dias/365;
jtEdad.setText(Integer.toString(edad));
}

También se pide que el campo de e-mail sea validado. Para ello uso este método, muy sencillo aunque efectivo, en el que lo que hago es comprobar si el valor introducido tiene una arroba y si dentro de la cadena está en una posición anterior al del último "punto" de la cadena.
De este modo, no aceptaría un email como este: correo.mail@es.
Pero sí uno como este:correo@mail.es

Código: [Seleccionar]
public boolean validarEmail() {
String email = jtEmail.getText();

if (email.isBlank())
return false;
else {
int arroba = email.indexOf('@');
int punto = email.lastIndexOf('.');
if (arroba == -1 || punto == -1)
return false;
else
return punto - arroba > 1;
}
}

Luego hay dos métodos para setear acciones a los dos botones del formulario, uno para registrar los datos y otro para cancelar y volver al formulario de login.
Esta clase nos mostrará una interfaz como esta:


Y cuando pulsemos el botón "registrar", cuya acción luego escribiremos en la clase Main, haremos que nos pida confirmación de los datos introducidos.


Y si confirmamos, se guardarán los datos en el archivo de texto, este nuevo usuario quedará logueado y se nos mostrará la pantalla del "Menú de Pasajeros"



Este menú, según el enunciado, solo tendrá esas dos opciones.
Voy a poner el código para crear ese panel, es prácticamente calcado al que usamos para escribir el "Panel de Administrador", solo que en lugar de 4 botones, tendremos solo 2.
Al igual que el de Administrador, de momento estos botones no van a tener acciones.

Código: [Seleccionar]
package gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class PanelPasajero extends JPanel {

private BotonOpcion btBuscaRuta;
private BotonOpcion btCompraBoletos;
private JButton btLogout;

public PanelPasajero() {

btBuscaRuta = new BotonOpcion("Buscador<br>de<br>Rutas");
btCompraBoletos = new BotonOpcion("Comprar<br>Boletos");
btLogout = new JButton("Cerrar Sesión");

setLayout(new BorderLayout());
add(new PanelNorte(), BorderLayout.NORTH);
add(new PanelCentral(), BorderLayout.CENTER);
add(new PanelSur(), BorderLayout.SOUTH);

}

private class PanelNorte extends JPanel {

public PanelNorte() {
JLabel titulo = new JLabel("Menú de Pasajeros");
titulo.setFont(new Font("Verdana", Font.ITALIC, 36));
add(titulo);
setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(20, 20, 0, 20),
BorderFactory.createRaisedSoftBevelBorder()));
}
}

private class PanelCentral extends JPanel {

public PanelCentral() {

setLayout(new GridLayout(1,1,15,15));
add(btBuscaRuta); add(btCompraBoletos);
setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
}
}

private class PanelSur extends JPanel {

public PanelSur() {
JPanel pnBoton = new JPanel();
pnBoton.add(btLogout);
add(pnBoton);
}
}

private class BotonOpcion extends JButton {

public BotonOpcion(String texto) {
super("<html><p style=\"text-align:center\">" + texto + "</p></html>");
setFont(new Font("Verdana", Font.BOLD, 18));
setFocusPainted(false);
setBackground(new Color(102, 204, 255));
setForeground(Color.WHITE);
setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEtchedBorder(),
BorderFactory.createEmptyBorder(10, 10, 10, 10)));
addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {}
@Override
public void mousePressed(MouseEvent e) {}
@Override
public void mouseReleased(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {
setForeground(new Color(204, 0, 0));
}
@Override
public void mouseExited(MouseEvent e) {
setForeground(Color.WHITE);
}
});
}
}

//Métodos
public void setAccionLogout(ActionListener accion) {
btLogout.addActionListener(accion);
}
}

Bien, tenemos escrito el código para modelar el panel registro de nuevos usuarios y el del menú de opciones del pasajero.
En el siguiente post voy a poner los cambios que hay que hacer en la clase Main para incluirlos en nuestro programa.
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: ayuda como puedo modificar un archivo txt en java con interfaz
« Respuesta #10 en: 18 de Abril 2021, 01:39 »
Esta es la clase Main con todos los cambios necesarios para poder usar los paneles que hemos escrito en el mensaje anterior:
Código: [Seleccionar]
package gui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

import usuario.*;

@SuppressWarnings("serial")
public class Main extends JFrame{

///Uusario que ha logueado, puede ser Admin o Pasajero
private Usuario logueado;

//Gestores
private GestorUsuario usuarios;

//Paneles
private PanelPrincipal pnPrincipal;
private PanelLogin pnLogin;
private PanelAdmin pnAdmin;
private PanelPasajero pnPasajero;
private PanelFormularioPasajero pnFormuPasajero;

public Main() {

usuarios = new GestorUsuario();
pnPrincipal = new PanelPrincipal();
pnLogin = new PanelLogin();
pnLogin.setAccionBotonLogin(new AccionLogin());
pnAdmin = new PanelAdmin();
pnAdmin.setAccionLogout(new AccionLogout());
pnPasajero = new PanelPasajero();
pnPasajero.setAccionLogout(new AccionLogout());
pnFormuPasajero = new PanelFormularioPasajero();
pnFormuPasajero.setAccionRegistrar(new AccionRegistrar());
pnFormuPasajero.setAccionCancelar(new AccionLogout());

//Añadimos cada panel al panel principal.
pnPrincipal.add(pnLogin, "login");
pnPrincipal.add(pnAdmin, "admin");
pnPrincipal.add(pnPasajero, "pasajero");
pnPrincipal.add(pnFormuPasajero, "formuPasajero");


setContentPane(pnPrincipal);

setTitle("Gestion de Terminales");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
}

//Acciones
/**
* Recoge los datos del formulario de login y permite acceder
* a un usuario registrado, o bien crear un nuevo registro.<br>
* Cuando el Usuario ha accedido al sistema, se mostrará un panel
* de opciones según si es Administrador o Pasajero.
*/
private class AccionLogin implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
//Recuperamos datos del formulario login
String[] datosLogin = pnLogin.getDatos();

if (datosLogin !=  null) {
//Preguntamos si es nuevo registro
if (pnLogin.esNuevoRegistro()) {
pnFormuPasajero.setCedula(datosLogin[0]);
pnFormuPasajero.setPassword(datosLogin[1]);
pnPrincipal.mostrarPanel("formuPasajero");
pnLogin.resetFormulario();
}
else {//Es un login normal
//Intentamos login con los datos
logueado = usuarios.login(datosLogin[0], datosLogin[1]);
//Comprobamos si ha tenido exito el login y que tipo usuario se trata
if (logueado == null)
JOptionPane.showMessageDialog(null,
"Los datos introducidos no coinciden con ningun Usuario",
"Login Usuario", JOptionPane.WARNING_MESSAGE);
else {
//Login exitoso. Se mostrará un nuevo panel, según tipo usuario
if (logueado instanceof Administrador)
pnPrincipal.mostrarPanel("admin");
else
pnPrincipal.mostrarPanel("pasajero");
//El formulario de login se resetea
pnLogin.resetFormulario();
}
}
}
}
}

private class AccionLogout implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
logueado = null;
pnPrincipal.mostrarPanel("login");
}
}


/**
* Recoge los datos del formulario para registrar un nuevo Pasajero.<br>
* Tras comprobaciones para validar esos datos pedirá registrarlo en el
* Gestor de Usuarios, logueará a este Usuario para que inicie sesión
* y mostrará su menú correspondiente.
*/
private class AccionRegistrar implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
//Recuperamos datos
Object[] datosPasajero = pnFormuPasajero.getDatos();
String cedula = (String) datosPasajero[0];
String password = (String) datosPasajero[1];
String nombre = (String) datosPasajero[2];
String eMail = (String) datosPasajero[3];
String genero = (String) datosPasajero[4];
Date fechaNac = (Date) datosPasajero[5];

//Validamos datos
if (!pnFormuPasajero.validarEmail())
JOptionPane.showMessageDialog(null, "Dirección e-mail no es válida",
"Registrar Usuario", JOptionPane.WARNING_MESSAGE);
else if (cedula.isBlank() || password.isBlank() || nombre.isBlank())
JOptionPane.showMessageDialog(null, "Debe rellenar todos los campos",
"Registrar Usuario", JOptionPane.WARNING_MESSAGE);
else {
int respuesta = JOptionPane.showConfirmDialog(null, "¿Desea registrarse con estos datos?",
"Registrar Usuario", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION) {
//Creamos Pasajero
Pasajero pas = new Pasajero(cedula, password, nombre, fechaNac, genero, eMail);
//Registramos, si es posible..
if (usuarios.registrarUsuario(pas)) {
JOptionPane.showMessageDialog(null, "Usuario Registrado",
"Registrar Usuario", JOptionPane.INFORMATION_MESSAGE);
pnFormuPasajero.resetFormulario();
logueado = pas;
pnPrincipal.mostrarPanel("pasajero");
}
}
}

}
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Main();
}
});
}
}

¿Qué es lo que ha cambiado?

Declaramos los nuevos paneles como atributos de clase:
Citar
public class Main extends JFrame{

   //Usuario que ha logueado, puede ser Admin o Pasajero
   private Usuario logueado;

   //Gestores
   private GestorUsuario usuarios;

   //Paneles
   private PanelPrincipal pnPrincipal;
   private PanelLogin pnLogin;
   private PanelAdmin pnAdmin;
   private PanelPasajero pnPasajero;
   private PanelFormularioPasajero pnFormuPasajero;

En el constructor, inicializamos esos paneles, le damos funcionalidad a sus botones de acción y los añadimos al "Panel Principal", el que tiene el CardLayout que gestiona el resto de paneles:

Citar
   public Main() {

      usuarios = new GestorUsuario();
      pnPrincipal = new PanelPrincipal();
      pnLogin = new PanelLogin();
      pnLogin.setAccionBotonLogin(new AccionLogin());
      pnAdmin = new PanelAdmin();
      pnAdmin.setAccionLogout(new AccionLogout());
      pnPasajero = new PanelPasajero();
      pnPasajero.setAccionLogout(new AccionLogout());
      pnFormuPasajero = new PanelFormularioPasajero();
      pnFormuPasajero.setAccionRegistrar(new AccionRegistrar());
      pnFormuPasajero.setAccionCancelar(new AccionLogout());


      //Añadimos cada panel al panel principal.
      pnPrincipal.add(pnLogin, "login");
      pnPrincipal.add(pnAdmin, "admin");
      pnPrincipal.add(pnPasajero, "pasajero");
      pnPrincipal.add(pnFormuPasajero, "formuPasajero");



      setContentPane(pnPrincipal);

      setTitle("Gestion de Terminales");
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      pack();
      setLocationRelativeTo(null);
      setVisible(true);
   }

En la clase ActionListener que corresponde al botón del formulario de Login, añadimos el código correspondiente a lo que ha de hacer cuando el JCheckBox de "Nuevo Registro" está seleccionado. Es decir, ha de pasar los valores de cédula y password que el usuario acaba de introducir al formulario de registrar nuevo usuario, y mostrarlo en pantalla.

Citar
   private class AccionLogin implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         //Recuperamos datos del formulario login
         String[] datosLogin = pnLogin.getDatos();

         if (datosLogin !=  null) {
            //Preguntamos si es nuevo registro
            if (pnLogin.esNuevoRegistro()) {
               pnFormuPasajero.setCedula(datosLogin[0]);
               pnFormuPasajero.setPassword(datosLogin[1]);
               pnPrincipal.mostrarPanel("formuPasajero");
               pnLogin.resetFormulario();
            }

            else {//Es un login normal
               //Intentamos login con los datos
               logueado = usuarios.login(datosLogin[0], datosLogin[1]);
               //Comprobamos si ha tenido exito el login y que tipo usuario se trata
               if (logueado == null)
                  JOptionPane.showMessageDialog(null,
                        "Los datos introducidos no coinciden con ningun Usuario",
                        "Login Usuario", JOptionPane.WARNING_MESSAGE);
               else {
                  //Login exitoso. Se mostrará un nuevo panel, según tipo usuario
                  if (logueado instanceof Administrador)
                     pnPrincipal.mostrarPanel("admin");
                  else
                     pnPrincipal.mostrarPanel("pasajero");
                  //El formulario de login se resetea
                  pnLogin.resetFormulario();
               }
            }
         }
      }
   }

Por último, se escribe una nueva clase ActionListener, la que se aplicará al botón de registrar al nuevo usuario.
Este código lo que hará será recuperar todos los datos introducidos en el formulario (que nos llega en el array de Object) y comprobará que los datos son válidos.

Si son válidos, se creará un nuevo objeto Pasajero con ellos y se pedirá al "Gestor de Usuarios" que lo registre en el ArrayList.
Si lo acepta (no lo aceptará si ya hay alguien con la misma cédula), entonces este usuario quedará logueado y se mostrará el "Menú de Pasajero"
Citar
   private class AccionRegistrar implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         //Recuperamos datos
         Object[] datosPasajero = pnFormuPasajero.getDatos();
         String cedula = (String) datosPasajero[0];
         String password = (String) datosPasajero[1];
         String nombre = (String) datosPasajero[2];
         String eMail = (String) datosPasajero[3];
         String genero = (String) datosPasajero[4];
         Date fechaNac = (Date) datosPasajero[5];

         //Validamos datos
         if (!pnFormuPasajero.validarEmail())
            JOptionPane.showMessageDialog(null, "Dirección e-mail no es válida",
                  "Registrar Usuario", JOptionPane.WARNING_MESSAGE);
         else if (cedula.isBlank() || password.isBlank() || nombre.isBlank())
            JOptionPane.showMessageDialog(null, "Debe rellenar todos los campos",
                  "Registrar Usuario", JOptionPane.WARNING_MESSAGE);
         else {
            int respuesta = JOptionPane.showConfirmDialog(null, "¿Desea registrarse con estos datos?",
                  "Registrar Usuario", JOptionPane.YES_NO_OPTION);
            if (respuesta == JOptionPane.YES_OPTION) {
               //Creamos Pasajero
               Pasajero pas = new Pasajero(cedula, password, nombre, fechaNac, genero, eMail);
               //Registramos, si es posible..
               if (usuarios.registrarUsuario(pas)) {
                  JOptionPane.showMessageDialog(null, "Usuario Registrado",
                        "Registrar Usuario", JOptionPane.INFORMATION_MESSAGE);
                  pnFormuPasajero.resetFormulario();
                  logueado = pas;
                  pnPrincipal.mostrarPanel("pasajero");
               }
            }
         }

      }
   }

Estos son los cambios hechos en la clase Main, pero queda otro cambio pendiente.

En la clase GestionUsuarios, se requiere que escribamos el código del método para registrar nuevos usuarios.
Este método es muy simple: Recibe el usuario que se ha creado en el Main según los datos del formulario de registro.
Comprueba si ya existe un Usuario igual (alguien con misma cédula).
Si existe alguien igual, informa en pantalla y retorna false para informar de que ha rechazado el registro.
Si no, entonces lo registra en el ArrayList, guarda en el archivo de texto y retorna true para anunciar que el registro ha sido aceptado.

Código: [Seleccionar]
public boolean registrarUsuario(Usuario usuario) {
//Primero comprobamos que no exista ya un usuario con misma cédula
if (usuarios.contains(usuario)) {
JOptionPane.showMessageDialog(null, "Ya existe un Usuario registrado con esta Cédula",
"Registrar Usuario", JOptionPane.WARNING_MESSAGE);
return false;
}
else {
usuarios.add(usuario);
guardarDatos();
return true;
}
}


Y con todo esto, ya podemos registrar nuevos Usuarios Pasajeros.

Lo siguiente sería comenzar a dar funciones a algúna opción del panel de Administrador.

NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Anonimuxx 30167832

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 9
    • Ver Perfil
Re: ayuda como puedo modificar un archivo txt en java con interfaz
« Respuesta #11 en: 18 de Abril 2021, 03:54 »
 ;D Hola, una pregunta bueno una duda es que en PanelFormularioPasajero,
el import de com.toedter.calendar.JDateChooser;
no me funciona quería saber si solo soy yo o hay otra cosa que hacer para importarlo ?
me dice algo como esto, package com.toedter.calendar does not exist----:



Anonimuxx 30167832

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 9
    • Ver Perfil
Re: ayuda como puedo modificar un archivo txt en java con interfaz
« Respuesta #12 en: 18 de Abril 2021, 11:17 »
 8) ya lo pude lograr funcionar me encontré en internet un Jcalendar-Master y lo ingrese en el src del proyecto, tranqui entiendo que no te alcance el tiempo pero me quedo con una buena explicación, me gustaría poder saber como hacer los métodos para ver si puedo entregarlo hoy pero jajaj no alcanza el tiempo 

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: ayuda como puedo modificar un archivo txt en java con interfaz
« Respuesta #13 en: 19 de Abril 2021, 01:14 »
Aunque se cumpla el plazo, intentaré seguir avanzando. Si sirve para aclararte conceptos de cara a próximas tareas, bienvenido sea.

Lo siguiente sería comenzar con la gestión de Terminales.
El enunciado indica que una Terminal tiene un ID autogenerado por el programa, un nombre, un lugar y un número de terminal (entre 1 y 2)
Del lugar, nos dan una lista determinada y solo podemos escoger un lugar de esa lista.
Además nos dice que esa lista tiene estar en una estructura de datos dentro del programa, no especifica cuál.

A mi me ha parecido adecuado crear un Enum (enumeración). Un Enum es un conjunto de valores determinados dentro de los cuáles podemos escoger.
En Java, un Enum es como una Clase, de la cuál no se pueden crear objetos, excepto los propios valores del Enum.
Como vamos a querer que esos valores se guarden en un archivo de texto, a cada uno de estos objetos valores/objetos podemos darle un atributo de tipo String. Este String será lo que se guardará en el archivo de texto cuando guardemos Terminales.
Y mediante este String, al leer los datos del archivo y tener que recrear a partir de ellos las Terminales, gracias a un método static que le incluyo al Enum, podremos relacionar el String con su valor Lugar correspondiente.

Código: [Seleccionar]
package terminal;

public enum Lugar {

SAN_JOSE("San José"), ALAJUELA("Alajuela"), HEREDIA("Heredia"),
CARTAGO("Cartago"), SAN_CARLOS("San Carlos"), PUNTARENAS("Puntarenas"),
LIMON("Limón");

private String nombre;

private Lugar(String nombre) {
this.nombre = nombre;
}

@Override
public String toString() {
return nombre;
}

/**
* Método estatico para, a partir de un String,
* identificar cuál es el objeto Lugar equivalente.<br>
* Esto será necesario cuando recuperemos datos del archivo txt,
* ya que el nombre del lugar se habrá guardado como un String, pero
* el programa va a trabajar con objetos Lugar.
* @param nomLugar String con el nombre del lugar, provendrá del archivo txt.
* @return Objeto Lugar equivalente.
*/
public static Lugar getLugar(String nomLugar) {
switch(nomLugar) {
case "San José":
return SAN_JOSE;
case "Alajuela":
return ALAJUELA;
case "Heredia":
return HEREDIA;
case "Cartago":
return CARTAGO;
case "San Carlos":
return SAN_CARLOS;
case "Puntarenas":
return PUNTARENAS;
case "Limón":
return LIMON;
default: //Será prácticamente imposible que se reciba un String distinto de los predefinidos.
return null; //Pero aún así contemplamos esa posibilidad.
}
}
}

Ahora que ya hemos definido la clase/enum Lugar, podemos crear la clase Terminal
Código: [Seleccionar]
package terminal;

/**
 * Clase para modelar una Terminal.<br>
 * El atributo lugar es del tipo "enumerado" Lugar.<br>
 * Se sobreescribe el método toString() para usarlo posteriormente
 * para mostrar los objetos en un JComboBox.<br>Un método similar
 * llamado toTXT() será el que usaremos para
 * cuando se guarden los datos en un archivo de texto.
 */
public class Terminal {

private String idTerminal;
private String nomTerminal;
private Lugar lugar;
private String numTerminal;

public Terminal(String idTerminal, String nomTerminal, Lugar lugar, String numTerminal) {
this.idTerminal = idTerminal;
this.nomTerminal = nomTerminal;
this.lugar = lugar;
this.numTerminal = numTerminal;
}

public String getIdTerminal() {
return idTerminal;
}

public void setIdTerminal(String idTerminal) {
this.idTerminal = idTerminal;
}

public String getNomTerminal() {
return nomTerminal;
}

public void setNomTerminal(String nomTerminal) {
this.nomTerminal = nomTerminal;
}

public Lugar getLugar() {
return lugar;
}

public void setLugar(Lugar lugar) {
this.lugar = lugar;
}

public String getNumTerminal() {
return numTerminal;
}

public void setNumTerminal(String numTerminal) {
this.numTerminal = numTerminal;
}

/**
* Este será el String que usaremos para escribir datos en archivo texto
*/
public String toTXT() {
return String.format("%s -- %s -- %s -- %s", idTerminal, nomTerminal, lugar, numTerminal);
}

/**
* Este String se usará principalmente para mostrar las Terminales en un ComboBox
* que permitirá seleccionarlas en el panel de Gestión de Terminales.
*/
@Override
public String toString() {
return String.format("%s -- %s", idTerminal, nomTerminal);
}

/**
* Dos terminales son equivalente si tienen el mismo ID.
*/
@Override
public boolean equals(Object objeto) {
if (objeto instanceof Terminal) {
Terminal otraTerminal = (Terminal) objeto;
return idTerminal.equals(otraTerminal.idTerminal);
}
else
return false;
}

}

Y tal como hicimos con los Usuarios, vamos a querer tener una clase que se dedique a la Gestión de Terminales, que tenga un ArrayList donde agruparlos, se encargue de leer y guardar en archivo de texto, etc..
Además tendrá un método para generar al azar un ID que sea único.

Fijémonos que en el método para agregar una nueva Terminal, se hacen dos comprobaciones.
Primero, asegurarse de que no hay otra con el mismo ID, algo que por otra parte debería ser imposible ya que cada nueva Terminal recibe un ID que ya se ha comprobado que es único.
Segundo, comprueba si en el Lugar asignado a esta nueva Terminal hay ya otras dos Terminales emplazadas.
Porque el enunciado dice que no puede haber más de dos Terminales en el mismo sitio, así que si se intenta registrar una tercera, será rechazada.


Código: [Seleccionar]
package terminal;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.JOptionPane;

/**
 * Esta clase gestionará un ArrayList con las Terminales disponibles.<br>
 * Se encargará de registrar y modificar terminales, así como de
 * guardar y leer el archivo txt con la información de las Terminales.
 */
public class GestorTerminal {

private ArrayList<Terminal> terminales;

public GestorTerminal() {
terminales = new ArrayList<Terminal>();
cargarDatos();
}

private void cargarDatos() {

try {
BufferedReader br = new BufferedReader(new FileReader("terminales.txt"));
String linea = br.readLine();

while(linea != null) {

//Separamos datos contenidos en la linea
String[] datos = linea.split(" -- ");
//Creamos una Terminal con los datos de esta línea
terminales.add(new Terminal(datos[0], datos[1], Lugar.getLugar(datos[2]), datos[3]));
//siguiente linea
linea = br.readLine();
}

br.close();

} catch (FileNotFoundException e) {
JOptionPane.showMessageDialog(null, "No se encuentra archivo: terminales.txt\n"
+ "Se intentará generar uno nuevo cuando se registre una Terminal nueva",
"Cargar Datos Terminales", JOptionPane.WARNING_MESSAGE);
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, "Error intentando leer: terminales.txt",
"Cargar Datos Terminales", JOptionPane.WARNING_MESSAGE);
} catch (Exception error) {
JOptionPane.showMessageDialog(null, "Error recuperando datos de: terminales.txt\n"
+ "Error:\n" + error.getLocalizedMessage(),
"Cargar Datos Terminales", JOptionPane.WARNING_MESSAGE);
}
}

private void guardarDatos() {
try {
BufferedWriter bw = new BufferedWriter(new FileWriter("terminales.txt", false));
//Por cada Terminal, creamos una línea de texto en el archivo
for (Terminal ter: terminales) {
bw.write(ter.toTXT());
bw.newLine();
}
bw.close();
} catch (IOException e) {
JOptionPane.showMessageDialog(null, "Error intentando guardar: terminales.txt",
"Guardar Datos Terminales", JOptionPane.WARNING_MESSAGE);
}
}

public boolean registrarTerminal(Terminal ter) {
/*
* Primero comprobamos si ya existe una Terminal con el mismo identificador.
* Esta posibilidad es muy remota ya que los identificadores son autogenerados
* por el sistema, pero por si a caso. 
*/
if (terminales.contains(ter)) {
JOptionPane.showMessageDialog(null, "Ya existe una Terminal registrada con este ID",
"Registrar Terminal", JOptionPane.WARNING_MESSAGE);
return false;
}
else if(cuentaTerminalesEnLugar(ter.getLugar()) >= 2 ) {
JOptionPane.showMessageDialog(null, "Ya existen dos Terminales en: " + ter.getLugar()
+ "\nNo pueden registrarse más.", "Registrar Terminal", JOptionPane.WARNING_MESSAGE);
return false;
}
else {
terminales.add(ter);
JOptionPane.showMessageDialog(null, "Nueva Terminal registrada",
"Registrar Terminal", JOptionPane.INFORMATION_MESSAGE);
guardarDatos();
return true;
}
}

/**
* Hace un recuento de cuántas Terminales existen en un
* Lugar concreto. Esto es necesario ya que hay impuesto
* un límite de máximo 2 Terminales en un mismo Lugar.<br>
* Así que antes de aceptar registrar una Terminal, hay que
* comprobar este recuento.
* @param lugar Lugar que se quiere consultar.
* @return Cantidad de Terminales existente en el Lugar especificado
*/
private int cuentaTerminalesEnLugar(Lugar lugar) {
int cont = 0;
for (Terminal ter: terminales)
if (ter.getLugar().equals(lugar))
cont++;

return cont;
}

/**
* Genera automáticamente un identificador para poder crear
* y registrar nuevas terminales.<br>
* EL identificador será un String con el formato "TERxxx"
* donde las x serán los digitos correspondientes a un número
* al azar entre 000 y 999.
* @return String con un ID único autogenerado.
*/
public String generaID() {

Random azar = new Random();
String id = "";
boolean esUnico = false;

while (!esUnico) {
//Generamos ID
id = String.format("TER%03d", azar.nextInt(1000));
esUnico = true;
//Comprobamos si es realmente único
for (Terminal ter: terminales)
if (ter.getIdTerminal().equals(id))
esUnico = false; //Se encontró una Terminal con ese ID, el bucle volverá a intentarlo
}

return id;
}

/**
* Crea un array primitivo con los objetos Terminal y los retorna.<br>
* Será muy útil para configurar un JComboBox en el panel de Gestión de Terminales.
* @return Array con los objetos Terminal.
*/
public Terminal[] getArrayTerminales() {
return terminales.toArray(new Terminal[terminales.size()]);
}

}

Esta clase no es definitiva y más adelante habrá que añadirle más cosas. Por ejemplo, un método para eliminar Terminales.
Pero bueno, ahora ya tenemos la parte del "modelo" básica para poder crear y guardar Terminales.

Para probarlo, tenemos que centrarnos ahora en la parte de la "vista", en la interfaz gráfica.
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: ayuda como puedo modificar un archivo txt en java con interfaz
« Respuesta #14 en: 19 de Abril 2021, 01:28 »
Tenemos que crear un nuevo panel que se dedique a la Gestión de Terminales. Tiene que servirnos para crear Terminales, consultarlas, modificarlas y eliminarlas.
Para no complicarnos con interfaces complejas, podemos hacerlo todo con un único formulario.
Se puede ofrecer un JComboBox con la lista de Terminales creadas, si es que las hay, para que el usuario pueda elegir una u otra.
Cada vez que elige una, se mostrarían su ID y nombre en campos de texto.
El Lugar y el número de Terminal, se mostrarían en otros JComboBox, ya que estos elementos han de ser seleccionados dentro de unos valores determinados.

De este modo podría modificar o eliminar Terminales, con los botones correspondientes.
Un tercer botón permitiría iniciar la creación de una nueva Terminal.
Durante el proceso de creación, no conviene que los otros botones sigan activos, ni tampoco el selector de Terminales (el JComboBox).

Esto me ha llevado a pensar en usar un boolean como atributo de clase, para hacer que el formulario tenga dos modos de funcionamiento diferentes.
Durante el "modo gestión", se puede seleccionar terminales, modificar y eliminar.

Pero cuando se pulsa el botón de Crear Terminal, se activa el "modo creación", que lo que hace es bloquear los otros botones y solo deja funcionando los necesario para introducir los datos de la nueva Terminal y pedir que sea registrada.

Otro atributo que tendrá esta clase, será un objeto Terminal que será una referencia al objeto Terminal que tenemos seleccionado en cada momento.
De este modo, si se quiere hacer modificaciones, tenemos a mano la Terminal a la que hay que aplicarle los cambios.

Este sería el código para crear el panel Gestión de Terminales. Fíjate que en su constructor, la hago llegar el array con la lista actual de Terminales registradas. Esto es necesario para poder inicializar el JComboBox de Terminales.
Código: [Seleccionar]
package gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

import terminal.*;

@SuppressWarnings("serial")
public class PanelTerminal extends JPanel{

//Terminal seleccionada en el formulario
Terminal seleccion;
//Este panel tendrá dos modalidades de funcionamiento: creación y gestión
boolean modoGestion;
//Mostrará terminales registradas para poder seleccionarlas
private JComboBox<Terminal> jcTerminales;
//Campos del formulario para registrar o modificar terminales
private JTextField jtIdTerminal;
private JTextField jtNombreTerminal;
private JComboBox<Lugar> jcLugar;
private JComboBox<String> jcNumTerminal;
//Botones de gestión
private BotonOpcion btCrear;
private BotonOpcion btModificar;
private BotonOpcion btEliminar;
//Para regresar al menú de administrador
private JButton btVolver;


public PanelTerminal(Terminal[] terminales) {

jtIdTerminal = new JTextField(8);
jtIdTerminal.setEditable(false);
jtNombreTerminal = new JTextField(8);
jcLugar = new JComboBox<Lugar>(Lugar.values());
jcNumTerminal = new JComboBox<String>(new String[] {"1", "2"});
btCrear = new BotonOpcion("Crear<br>Terminal");
btModificar = new BotonOpcion("Modificar<br>Terminal");
btEliminar = new BotonOpcion("Eliminar<br>Terminal");
btVolver = new JButton("Volver Menú Administración");

jcTerminales = new JComboBox<Terminal>();
jcTerminales.addItemListener(new SeleccionTerminal());
actualizarPanel(terminales);
setModoGestion();


setLayout(new BorderLayout());
add(new PanelNorte(), BorderLayout.NORTH);
add(new PanelCentro(), BorderLayout.CENTER);
add(new PanelSur(), BorderLayout.SOUTH);
}

private class PanelNorte extends JPanel {

public PanelNorte() {
JLabel titulo = new JLabel("Gestión de Terminales");
titulo.setFont(new Font("Verdana", Font.ITALIC, 36));
add(titulo);
setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(20, 20, 0, 20),
BorderFactory.createRaisedSoftBevelBorder()));
}
}

private class PanelCentro extends JPanel {

public PanelCentro() {

JPanel pnSup = new JPanel();
pnSup.add(new JLabel("Seleccione terminal: "));
pnSup.add(jcTerminales);

JPanel pnCen = new JPanel();
pnCen.setLayout(new GridLayout(2,2));
pnCen.add(new PanelConComponente("ID: ", jtIdTerminal));
pnCen.add(new PanelConComponente("Nombre: ", jtNombreTerminal));
pnCen.add(new PanelConComponente("Lugar: ", jcLugar));
pnCen.add(new PanelConComponente("Número: ", jcNumTerminal));
pnCen.setBorder(BorderFactory.createTitledBorder("Datos de la Terminal"));

JPanel pnInf = new JPanel();
pnInf.setLayout(new GridLayout(1,3,10,10));
pnInf.add(btCrear); pnInf.add(btModificar); pnInf.add(btEliminar);
pnInf.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createRaisedSoftBevelBorder(),
BorderFactory.createEmptyBorder(5, 5, 5, 5)));

setLayout(new BorderLayout());
add(pnSup, BorderLayout.NORTH);
add(pnCen, BorderLayout.CENTER);
add(pnInf, BorderLayout.SOUTH);
setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));

}
}

private class PanelConComponente extends JPanel {

public PanelConComponente(String texto, JComponent componente) {
add(new JLabel(texto)); add(componente);
}
}

private class PanelSur extends JPanel {

public PanelSur() {
JPanel pnBoton = new JPanel();
pnBoton.add(btVolver);
add(pnBoton);
}
}


private class BotonOpcion extends JButton {

public BotonOpcion(String texto) {
super("<html><p style=\"text-align:center\">" + texto + "</p></html>");
setFont(new Font("Verdana", Font.BOLD, 14));
setFocusPainted(false);
setBackground(new Color(102, 204, 255));
setForeground(Color.WHITE);
setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEtchedBorder(),
BorderFactory.createEmptyBorder(10, 10, 10, 10)));
addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {}
@Override
public void mousePressed(MouseEvent e) {}
@Override
public void mouseReleased(MouseEvent e) {}
@Override
public void mouseEntered(MouseEvent e) {
setForeground(new Color(204, 0, 0));
}
@Override
public void mouseExited(MouseEvent e) {
setForeground(Color.WHITE);
}
});
}
}

//Métodos
/**
* Activa el "modo gestión".<br>
* Este modo es el normal, todos los botones están activos así como
* el ComboBox para seleccionar terminal, si es que existen terminales.<br>
* El botón "Crear" permanece activo y si se le pulsa, se activará el
* "modo creación".
*/
public void setModoGestion() {
modoGestion = true;
if (jcTerminales.getItemCount() > 0) {
jcTerminales.setEnabled(true);
btModificar.setEnabled(true);
btEliminar.setEnabled(true);
jtNombreTerminal.setEditable(true);
jcLugar.setEnabled(true);
jcNumTerminal.setEnabled(true);
}
else { //No hay Terminales para seleccionar en el JComboBox, no tiene sentido activar controles
jcTerminales.setEnabled(false);
btModificar.setEnabled(false);
btEliminar.setEnabled(false);
jtNombreTerminal.setEditable(false);
jcLugar.setEnabled(false);
jcNumTerminal.setEnabled(false);
}
btCrear.setText("<html><p style=\"text-align:center\">Crear<br>Terminal</p></html>");
}

/**
* Activa el "modo creacion".<br>
* Este modo se activa cuando se va a crear una nueva Terminal,
* en cuyo caso se desactivan los botones de "modificar" y "eliminar"
* terminales, así como el ComboBox para escoger terminales.<br>
* El botón "Crear" cambia su texto a "Registrar" y si se le pulsa,
* intentará registrar una nueva Terminal con los datos introducidos
* y si tiene éxito, actualizará el ComboBox de terminales y volverá de nuevo
* al "modo gestión".
*/
public void setModoCrear() {
modoGestion = false;
jtNombreTerminal.setEditable(true);
jcLugar.setEnabled(true);
jcNumTerminal.setEnabled(true);
jcTerminales.setEnabled(false);
btModificar.setEnabled(false);
btEliminar.setEnabled(false);
btCrear.setText("<html><p style=\"text-align:center\">Registrar<br>Terminal</p></html>");
}

/**
* Setea un ID en el campo correspondiente.<br>
* @param id String con el ID a setear.
*/
public void setID(String id) {
jtIdTerminal.setText(id);
}

/**
* Construye una Terminal con los datos proporcionados y la retorna<br>
* En la clase Main se evaluará si esta Terminal cumple los requisitos
* para poder ser registrada.
* @return Objeto Terminal según datos formulario.
*/
public Terminal getTerminal() {
String id = jtIdTerminal.getText();
String nombre = jtNombreTerminal.getText();
Lugar lugar = (Lugar) jcLugar.getSelectedItem();
String numero = (String) jcNumTerminal.getSelectedItem();

if (nombre.isBlank()) {
JOptionPane.showMessageDialog(null, "Ha de dar un nombre a la Terminal",
"Registrar Terminal", JOptionPane.WARNING_MESSAGE);
jtNombreTerminal.requestFocusInWindow();
return null;
}
else {
return new Terminal(id, nombre, lugar, numero);
}
}

public void actualizarPanel(Terminal[] terminales) {
//Renovamos combobox de terminales
jcTerminales.removeAllItems();
if (terminales.length > 0) {
for (Terminal ter: terminales)
jcTerminales.addItem(ter);
//Seleccionamos el último añadido a la lista
jcTerminales.setSelectedIndex(terminales.length - 1);
seleccion = (Terminal) jcTerminales.getSelectedItem();
mostrarSeleccionado();
}
}

private void mostrarSeleccionado() {
jtIdTerminal.setText(seleccion.getIdTerminal());
jtNombreTerminal.setText(seleccion.getNomTerminal());
jcLugar.setSelectedItem(seleccion.getLugar());
jcNumTerminal.setSelectedItem(seleccion.getNumTerminal());
}

public void setAccionVolver(ActionListener accion) {
btVolver.addActionListener(accion);
}

public void setAccionCrear(ActionListener accion) {
btCrear.addActionListener(accion);
}

//ActionListener
private class SeleccionTerminal implements ItemListener {
@Override
public void itemStateChanged(ItemEvent e) {
if (jcTerminales.getItemCount() > 0) {
seleccion = (Terminal) jcTerminales.getSelectedItem();
mostrarSeleccionado();
}
}
}
}

El siguiente paso es agregar todas esas novedades a la clase Main, tanto el panel de Gestión de Terminales ("vista"), como el gestor de terminales("modelo").
La clase Main quedaría así:
Código: [Seleccionar]
package gui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

import terminal.*;
import usuario.*;

@SuppressWarnings("serial")
public class Main extends JFrame{

//Usuario que ha logueado, puede ser Admin o Pasajero
private Usuario logueado;

//Gestores
private GestorUsuario usuarios;
private GestorTerminal terminales;

//Paneles
private PanelPrincipal pnPrincipal;
private PanelLogin pnLogin;
private PanelAdmin pnAdmin;
private PanelPasajero pnPasajero;
private PanelFormularioPasajero pnFormuPasajero;
private PanelTerminal pnTerminal;

public Main() {

usuarios = new GestorUsuario();
terminales = new GestorTerminal();
pnPrincipal = new PanelPrincipal();
pnLogin = new PanelLogin();
pnLogin.setAccionBotonLogin(new AccionLogin());
pnAdmin = new PanelAdmin();
pnAdmin.setAccionLogout(new AccionLogout());
pnAdmin.setAccionTerminal(new AccionAdministrarTerminal());
pnPasajero = new PanelPasajero();
pnPasajero.setAccionLogout(new AccionLogout());
pnFormuPasajero = new PanelFormularioPasajero();
pnFormuPasajero.setAccionRegistrar(new AccionRegistrar());
pnFormuPasajero.setAccionCancelar(new AccionLogout());
pnTerminal = new PanelTerminal(terminales.getArrayTerminales());
pnTerminal.setAccionCrear(new AccionCrearTerminal());
pnTerminal.setAccionVolver(new AccionVolverAdministracion());

//Añadimos cada panel al panel principal.
pnPrincipal.add(pnLogin, "login");
pnPrincipal.add(pnAdmin, "admin");
pnPrincipal.add(pnPasajero, "pasajero");
pnPrincipal.add(pnFormuPasajero, "formuPasajero");
pnPrincipal.add(pnTerminal, "terminal");


setContentPane(pnPrincipal);

setTitle("Gestion de Terminales");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
}

//Acciones
/**
* Recoge los datos del formulario de login y permite acceder
* a un usuario registrado, o bien crear un nuevo registro.<br>
* Cuando el Usuario ha accedido al sistema, se mostrará un panel
* de opciones según si es Administrador o Pasajero.
*/
private class AccionLogin implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
//Recuperamos datos del formulario login
String[] datosLogin = pnLogin.getDatos();

if (datosLogin !=  null) {
//Preguntamos si es nuevo registro
if (pnLogin.esNuevoRegistro()) {
pnFormuPasajero.setCedula(datosLogin[0]);
pnFormuPasajero.setPassword(datosLogin[1]);
pnPrincipal.mostrarPanel("formuPasajero");
pnLogin.resetFormulario();
}
else {//Es un login normal
//Intentamos login con los datos
logueado = usuarios.login(datosLogin[0], datosLogin[1]);
//Comprobamos si ha tenido exito el login y que tipo usuario se trata
if (logueado == null)
JOptionPane.showMessageDialog(null,
"Los datos introducidos no coinciden con ningun Usuario",
"Login Usuario", JOptionPane.WARNING_MESSAGE);
else {
//Login exitoso. Se mostrará un nuevo panel, según tipo usuario
if (logueado instanceof Administrador)
pnPrincipal.mostrarPanel("admin");
else
pnPrincipal.mostrarPanel("pasajero");
//El formulario de login se resetea
pnLogin.resetFormulario();
}
}
}
}
}

private class AccionLogout implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
logueado = null;
pnPrincipal.mostrarPanel("login");
}
}


/**
* Recoge los datos del formulario para registrar un nuevo Pasajero.<br>
* Tras comprobaciones para validar esos datos pedirá registrarlo en el
* Gestor de Usuarios, logueará a este Usuario para que inicie sesión
* y mostrará su menú correspondiente.
*/
private class AccionRegistrar implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
//Recuperamos datos
Object[] datosPasajero = pnFormuPasajero.getDatos();
String cedula = (String) datosPasajero[0];
String password = (String) datosPasajero[1];
String nombre = (String) datosPasajero[2];
String eMail = (String) datosPasajero[3];
String genero = (String) datosPasajero[4];
Date fechaNac = (Date) datosPasajero[5];

//Validamos datos
if (!pnFormuPasajero.validarEmail())
JOptionPane.showMessageDialog(null, "Dirección e-mail no es válida",
"Registrar Usuario", JOptionPane.WARNING_MESSAGE);
else if (cedula.isBlank() || password.isBlank() || nombre.isBlank())
JOptionPane.showMessageDialog(null, "Debe rellenar todos los campos",
"Registrar Usuario", JOptionPane.WARNING_MESSAGE);
else {
int respuesta = JOptionPane.showConfirmDialog(null, "¿Desea registrarse con estos datos?",
"Registrar Usuario", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION) {
//Creamos Pasajero
Pasajero pas = new Pasajero(cedula, password, nombre, fechaNac, genero, eMail);
//Registramos, si es posible..
if (usuarios.registrarUsuario(pas)) {
JOptionPane.showMessageDialog(null, "Usuario Registrado",
"Registrar Usuario", JOptionPane.INFORMATION_MESSAGE);
pnFormuPasajero.resetFormulario();
logueado = pas;
pnPrincipal.mostrarPanel("pasajero");
}
}
}

}
}

private class AccionAdministrarTerminal implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
pnPrincipal.mostrarPanel("terminal");
}
}

private class AccionCrearTerminal implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {

if (pnTerminal.modoGestion) {
//Si está en "modo gestion", pasamos al "modo crear"
pnTerminal.setModoCrear();
pnTerminal.setID(terminales.generaID());
}
else {
/*
* Si está en "modo crear", comprobaremos si hay datos
* para crear una Terminal, registrarla y volver al
* "modo gestion"
*/
Terminal nueva = pnTerminal.getTerminal();
if (nueva != null) {
if (terminales.registrarTerminal(nueva)) {
//Si la terminal ha sido aceptada, hay que actualizar el panel Terminal
pnTerminal.actualizarPanel(terminales.getArrayTerminales());
pnTerminal.setModoGestion();
}
}
}

}
}

private class AccionVolverAdministracion implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
pnPrincipal.mostrarPanel("admin");
}
}



public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Main();
}
});
}
}

En el siguiente post (en este no me cabe, demasiadas líneas de código) vemos en detalle, los cambios que hacemos en la clase Main.
« Última modificación: 19 de Abril 2021, 01:45 por Kabuto »
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: ayuda como puedo modificar un archivo txt en java con interfaz
« Respuesta #15 en: 19 de Abril 2021, 02:08 »
Señalo en rojo los cambios.
Primero añadir el gestor y el panel como atributos de clase:
Citar
public class Main extends JFrame{

   //Usuario que ha logueado, puede ser Admin o Pasajero
   private Usuario logueado;

   //Gestores
   private GestorUsuario usuarios;
   private GestorTerminal terminales;

   //Paneles
   private PanelPrincipal pnPrincipal;
   private PanelLogin pnLogin;
   private PanelAdmin pnAdmin;
   private PanelPasajero pnPasajero;
   private PanelFormularioPasajero pnFormuPasajero;
   private PanelTerminal pnTerminal;

En el constructor, inicializamos ambos objetos.
Al panel de gestión, le añadiremos dos ActionListener, uno es para el botón "volver" del formulario de Gestión Terminales, que lo que hace es regresar al usuario al Panel de Administrador.
La otra acción es la que corresponde al botón de crear/registrar nueva Terminal.
De momento, los botones de modificar y eliminar, no tendrán ActionListener todavía.

No olvidemos añadir el nuevo panel al "Panel Principal" que gestiona todos los paneles.

En color verde, señalo una línea importante. Es en la que al Panel de Administrador, le damos una acción al botón de "gestionar terminales".

Citar
   public Main() {

      usuarios = new GestorUsuario();
      terminales = new GestorTerminal();
      pnPrincipal = new PanelPrincipal();
      pnLogin = new PanelLogin();
      pnLogin.setAccionBotonLogin(new AccionLogin());
      pnAdmin = new PanelAdmin();
      pnAdmin.setAccionLogout(new AccionLogout());
      pnAdmin.setAccionTerminal(new AccionAdministrarTerminal());
      pnPasajero = new PanelPasajero();
      pnPasajero.setAccionLogout(new AccionLogout());
      pnFormuPasajero = new PanelFormularioPasajero();
      pnFormuPasajero.setAccionRegistrar(new AccionRegistrar());
      pnFormuPasajero.setAccionCancelar(new AccionLogout());
      pnTerminal = new PanelTerminal(terminales.getArrayTerminales());
      pnTerminal.setAccionCrear(new AccionCrearTerminal());
      pnTerminal.setAccionVolver(new AccionVolverAdministracion());


      //Añadimos cada panel al panel principal.
      pnPrincipal.add(pnLogin, "login");
      pnPrincipal.add(pnAdmin, "admin");
      pnPrincipal.add(pnPasajero, "pasajero");
      pnPrincipal.add(pnFormuPasajero, "formuPasajero");
      pnPrincipal.add(pnTerminal, "terminal");


      setContentPane(pnPrincipal);

      setTitle("Gestion de Terminales");
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      pack();
      setLocationRelativeTo(null);
      setVisible(true);
   }

Vamos a ver ahora los ActionListener que hay que añadir.
Uno es el que aplicamos al botón "Gestionar Terminales" del Panel de Administrador. Consiste en simplemente pedir que se muestre el nuevo panel de Gestión de Terminales.
Código: [Seleccionar]
private class AccionAdministrarTerminal implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
pnPrincipal.mostrarPanel("terminal");
}
}

Otro es la acción para el botón "volver" del panel de Gestión de Terminales. Lo que hace es volver al Panel de Administrador.

Código: [Seleccionar]
private class AccionVolverAdministracion implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
pnPrincipal.mostrarPanel("admin");
}
}

Por último, la acción para crear un Terminal.
En esta vemos que su funcionalidad varía según el modo actualmente activo (lo sabemos por el atributo boolean) en el panel de Gestión de Terminales.
Si está en "modo gestión", se activa el "modo crear" y seteamos en el formulario un nuevo ID autogenerado por el gestor de terminales para poder crear una Terminal nueva. Lo señalo en verde.

Si ya está activo el "modo crear", lo que hay que hacer es recoger los datos del formulario, crear una Terminal y pasársela al gestor de terminales para que la registre (si cumple los requisitos necesarios).
Si se acepta el registro, se actualiza el JComboBox del panel de Gestión de Terminales y se regresa al "modo gestión". Lo señalo en rojo

Citar
   private class AccionCrearTerminal implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         
         if (pnTerminal.modoGestion) {
            //Si está en "modo gestion", pasamos al "modo crear"
            pnTerminal.setModoCrear();
            pnTerminal.setID(terminales.generaID());
         }

         else {
            /*
             * Si está en "modo crear", comprobaremos si hay datos
             * para crear una Terminal, registrarla y volver al
             * "modo gestion"
             */

            Terminal nueva = pnTerminal.getTerminal();
            if (nueva != null) {
               if (terminales.registrarTerminal(nueva)) {
                  //Si la terminal ha sido aceptada, hay que actualizar el panel Terminal
                  pnTerminal.actualizarPanel(terminales.getArrayTerminales());
                  pnTerminal.setModoGestion();
               }

            }
         }
         
      }
   }

Si ponemos en marcha el programa y entramos como Administrador, ahora podemos acceder al panel de Gestión de Terminales


Al acceder al nuevo panel, como es la primera vez que lo iniciamos y aún no hemos registrado terminales, casi todo el formulario aparece desactivado.

Solo están activos el botón para volver al panel de Administrador, y el de Crear Terminal.
Este será el botón que vamos a pulsar, y lo que ocurre es que se activa el "modo creación".



Vemos que el campo ID ha recibido un identificador al azar. Podemos ponerle un nombre, seleccionar un Lugar y un número de terminal.
También vemos que el botón "crear", ahora pone "registrar".
Si lo pulsamos, la nueva Terminal queda registrada y automáticamente se actualiza el JComboBox.
Si registramos unas cuantas terminales más, veremos que el JCombobox va creciendo y podemos seleccionar cualquier Terminal para ver sus datos.



Si intentamos crear más de dos terminales en un mismo Lugar, no nos lo permite.

Hay un par de fallos. Por ejemplo, si entramos en el "modo creación", la única forma de salir de este modo es registrando una Terminal, es decir, no podemos cancelar el proceso de creación, ni siquiera regresando al panel de Administrador y volviendo de nuevo a Gestionar Terminales

Otro, algo que no había pensado hasta ahora mismo, es que supongo que al crear dos terminales en un mismo Lugar, estas terminales no pueden tener el mismo número. Es decir, si una tiene el número de terminal 1, pues la otra obligatoriamente tendrá que ser 2.
El enunciado creo que no dice nada de esto, pero suena lógico.

En fin, son detalles menores que se pueden corregir más adelante. Lo interesante ahora sería seguir con lo de "Modificar" y "Eliminar" Terminales, para así poder pasar a la Gestión de Unidades.
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: ayuda como puedo modificar un archivo txt en java con interfaz
« Respuesta #16 en: 20 de Abril 2021, 02:02 »
Ya tengo las funcionalidades de "modificar" y "eliminar" Terminal.

En la clase GestionTerminales añadimos estos dos métodos:

Código: [Seleccionar]
public void modificarTerminal(Terminal ter) {
//Buscamos la Terminal equivalente y transferimos los atributos
boolean modificacionAceptada = true;
for (Terminal terminal: terminales) {
if (terminal.equals(ter)) {
//Si el lugar es el mismo, no requiere comprobación previa
if (terminal.getLugar().equals(ter.getLugar())) {
terminal.setNomTerminal(ter.getNomTerminal());
terminal.setNumTerminal(ter.getNumTerminal());
}
else { //Lugar es distinto, requiere comprobación
if (cuentaTerminalesEnLugar(ter.getLugar()) >= 2 ) {
JOptionPane.showMessageDialog(null, "Ya existen dos Terminales en: " + ter.getLugar()
+ "\nNo se puede aceptar este cambio", "Modificar Terminal", JOptionPane.WARNING_MESSAGE);
modificacionAceptada = false;
}
else {
terminal.setNomTerminal(ter.getNomTerminal());
terminal.setLugar(ter.getLugar());
terminal.setNumTerminal(ter.getNumTerminal());
}
}
//Detenemos bucle for
break;
}
}

if (modificacionAceptada) {
JOptionPane.showMessageDialog(null, "Terminal modificada",
"Modificar Terminal", JOptionPane.INFORMATION_MESSAGE);
guardarDatos();
}
}

Código: [Seleccionar]
public boolean borrarTerminal(Terminal ter) {
int respuesta = JOptionPane.showConfirmDialog(null, "¿Confirma que desea eliminar esta Terminal",
"Eliminar Terminal", JOptionPane.YES_NO_OPTION);

if (respuesta == JOptionPane.YES_OPTION && terminales.remove(ter)) {
guardarDatos();
return true;
}
else
return false;
}

Son muy sencillos, ambos reciben un objeto Terminal, que es el que nos proporciona el Panel de Gestión de Terminales con los datos del formulario.

Para modificar, se busca el equivalente en el ArrayList y se le transfieren los datos de los atributos.
En el caso de que se haya modificado el Lugar, primero se comprueba si este cambio es posible debido a la limitación de solo dos Terminales en un mismo Lugar.

Para eliminar, simplemente se pide confirmación antes de eliminar del ArrayList.

En la clase PanelTerminal, solo hay que añadir dos métodos más, que serán los encargados de setear las acciones que vamos a escribir en el Main.

Código: [Seleccionar]
public void setAccionModificar(ActionListener accion) {
btModificar.addActionListener(accion);
}

public void setAccionEliminar(ActionListener accion) {
btEliminar.addActionListener(accion);
}

Y ahora sí en la clase Main escribimos la acciones.

Son muy simples, para modificar, pedimos al PanelTerminal que nos de la Terminal modificada y se la pasamos al gestor de terminales que ya sabe lo que hay que hacer.

Código: [Seleccionar]
private class AccionModificarTerminal implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Terminal modificada = pnTerminal.getTerminal();
if (modificada != null)
terminales.modificarTerminal(modificada);
}
}

Y para borrar Terminal, muy parecido, solo que esta vez deberemos actualizar el JComboBox para que no figure la Terminal que ha sido eliminada:
Código: [Seleccionar]
private class AccionBorrarTerminal implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Terminal borrar = pnTerminal.getTerminal();
if (borrar != null) {
if (terminales.borrarTerminal(borrar)) {
JOptionPane.showMessageDialog(null, "Terminal Eliminada",
"Eliminar Terminal", JOptionPane.INFORMATION_MESSAGE);
pnTerminal.actualizarPanel(terminales.getArrayTerminales());
}
}
}
}

No olvidemos setear estas acciones al PanelTerminal desde el constructor de Main:
Código: [Seleccionar]
pnTerminal.setAccionModificar(new AccionModificarTerminal());
pnTerminal.setAccionEliminar(new AccionBorrarTerminal());

Y listo, con esto acabaríamos con las Terminales.

Bueno, no del todo, porque el enunciado establece que una Terminal no puede ser eliminada, ni modificada, si ya está asignada a una Ruta.
Pero como aún no hemos llegado a las Rutas, pues esta limitación habrá que dejarla para más adelante.
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Anonimuxx 30167832

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 9
    • Ver Perfil
Re: ayuda como puedo modificar un archivo txt en java con interfaz
« Respuesta #17 en: 20 de Abril 2021, 05:48 »
hola, si ese fue unas de las  partes del enunciado que no pude hacer porque no sabia como hacerlo, me refiero ( que una Terminal no puede ser eliminada, ni modificada, si ya está asignada a una Ruta.)

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: ayuda como puedo modificar un archivo txt en java con interfaz
« Respuesta #18 en: 20 de Abril 2021, 11:19 »
hola, si ese fue unas de las  partes del enunciado que no pude hacer porque no sabia como hacerlo, me refiero ( que una Terminal no puede ser eliminada, ni modificada, si ya está asignada a una Ruta.)

Aún no he llegado a eso, primero habría que ponerse con la gestión de Unidades, pero si estoy rumiando en mi mente en cómo se podría resolver esa parte.

Supongo que lo más probable es que, puesto seguramente haremos una clase que se dedique a gestionar Rutas, le podremos escribir un método de tipo boolean que reciba una Terminal y nos diga si actualmente está asignada a alguna Ruta o no.

Así, antes de aceptar ninguna modificación o eliminación, preguntaremos al gestor de Rutas.

Incluso, se puede valorar añadir un atributo boolean a las Terminales que cuando esté asignada a una Ruta tenga valor TRUE y cuando no, sea FALSE.
Usando ese boolean, podemos hacer que el formulario de Gestión de Terminales desactive automáticamente los botones de "modificar" y "eliminar" cuando en el ComboBox seleccionamos una Terminal que está asignada a alguna Ruta.
Pero esto implicaría añadir más código extra, ya veremos...
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: ayuda como puedo modificar un archivo txt en java con interfaz
« Respuesta #19 en: 21 de Abril 2021, 01:21 »
Algo he podido avanzar, no mucho.
He escrito lo que vendría a ser el "modelo" de las Unidades, es decir, la clase Unidad y la clase que gestionaría las Unidades.
En realidad es todo muy parecido a las clases ya escritas para  la gestión de Terminales: guardar en txt, leerlo, registrar Unidad, modificar, eliminar....generar una placa al azar que sea única, un método para retornar las Unidades registradas en un array primitivo y así poder mostrarlas en un ComboBox rápidamente...
La lógica a seguir es la misma, solo cambia la entidad que se va a gestionar.

Esta sería la clase Unidad:
Código: [Seleccionar]
public final class Unidad {

private String placa;
private int capacidad;
private String nombreTerminal;

public Unidad(String placa, int capacidad, String nombreTerminal) {
this.placa = placa;
this.capacidad = capacidad;
this.nombreTerminal = nombreTerminal;
}

public String getPlaca() {
return placa;
}

public void setPlaca(String placa) {
this.placa = placa;
}

public int getCapacidad() {
return capacidad;
}

public void setCapacidad(int capacidad) {
this.capacidad = capacidad;
}

public String getNombreTerminal() {
return nombreTerminal;
}

public void setNombreTerminal(String nombreTerminal) {
this.nombreTerminal = nombreTerminal;
}

public String toTXT() {
return String.format("%s -- %d -- %s", placa, capacidad, nombreTerminal);
}

@Override
public String toString() {
return String.format("%s -- %s", placa, nombreTerminal);
}

@Override
public boolean equals(Object objeto) {
if (objeto instanceof Unidad) {
Unidad otraUnidad = (Unidad) objeto;
return placa.equals(otraUnidad.placa);
}
else
return false;
}

}

Y la clase GestorUnidad:
Código: [Seleccionar]
public final class GestorUnidad {

private ArrayList<Unidad> unidades;

public GestorUnidad() {
unidades = new ArrayList<Unidad>();
cargarDatos();
}

private void cargarDatos() {

try {
BufferedReader br = new BufferedReader(new FileReader("unidades.txt"));
String linea = br.readLine();

while(linea != null) {

//Separamos datos contenidos en la linea
String[] datos = linea.split(" -- ");
//Creamos una Unidad con los datos de esta línea
unidades.add(new Unidad(datos[0], Integer.valueOf(datos[1]), datos[2]));
//siguiente linea
linea = br.readLine();
}

br.close();

} catch (FileNotFoundException e) {
JOptionPane.showMessageDialog(null, "No se encuentra archivo: unidades.txt\n"
+ "Se intentará generar uno nuevo cuando se registre una Unidad nueva",
"Cargar Datos Unidades", JOptionPane.WARNING_MESSAGE);
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, "Error intentando leer: unidades.txt",
"Cargar Datos Unidades", JOptionPane.WARNING_MESSAGE);
} catch (Exception error) {
JOptionPane.showMessageDialog(null, "Error recuperando datos de: unidades.txt\n"
+ "Error:\n" + error.getLocalizedMessage(),
"Cargar Datos Unidades", JOptionPane.WARNING_MESSAGE);
}
}

private void guardarDatos() {
try {
BufferedWriter bw = new BufferedWriter(new FileWriter("unidades.txt", false));
//Por cada Unidad, creamos una línea de texto en el archivo
for (Unidad und: unidades) {
bw.write(und.toTXT());
bw.newLine();
}
bw.close();
} catch (IOException e) {
JOptionPane.showMessageDialog(null, "Error intentando guardar: unidades.txt",
"Guardar Datos Unidades", JOptionPane.WARNING_MESSAGE);
}
}

public boolean registrarUnidad(Unidad und) {
if (unidades.contains(und)) {
JOptionPane.showMessageDialog(null, "Ya existe una Unidad registrada con esta placa",
"Registrar Unidad", JOptionPane.WARNING_MESSAGE);
return false;
}
else if (cuentaTerminalesAsignadas(und.getNombreTerminal()) >= 2) {
JOptionPane.showMessageDialog(null, "Ya existen dos Unidades asignadas a la Terminal: "
+ und.getNombreTerminal() +"\nDeberá asignar esta Unidad a otra Terminal",
"Registrar Unidad", JOptionPane.WARNING_MESSAGE);
return false;
}
else {
unidades.add(und);
JOptionPane.showMessageDialog(null, "Nueva Unidad registrada",
"Registrar Unidad", JOptionPane.INFORMATION_MESSAGE);
guardarDatos();
return true;
}
}

public void modificarUnidad(Unidad und) {
//Buscamos la Unidad correspondiente y transferimos atributos
boolean modificacionAceptada = true;
for (Unidad unidad: unidades) {
if (unidad.equals(und)) {
//Si no varía la terminal asignada, no se requiere comprobación extra
if (unidad.getNombreTerminal().equals(und.getNombreTerminal()))
unidad.setCapacidad(und.getCapacidad()); //Único atributo que puede variar es capacidad
else {
//Terminal asignada varía. Hay que comprobar
if (cuentaTerminalesAsignadas(und.getNombreTerminal()) >= 2) {
JOptionPane.showMessageDialog(null, "Ya existen dos Unidades asignadas a la Terminal: "
+ und.getNombreTerminal() +"\nNo se puede aceptar este cambio",
"Modificar Unidad", JOptionPane.WARNING_MESSAGE);
modificacionAceptada = false;
}
else {
unidad.setCapacidad(und.getCapacidad());
unidad.setNombreTerminal(und.getNombreTerminal());
}
}
break;
}
}

if (modificacionAceptada) {
JOptionPane.showMessageDialog(null, "Unidad modificada",
"Modificar Unidad", JOptionPane.INFORMATION_MESSAGE);
guardarDatos();
}

}

public boolean borrarTerminal(Unidad und) {
int respuesta = JOptionPane.showConfirmDialog(null, "¿Confirma que desea eliminar esta Unidad",
"Eliminar Unidad", JOptionPane.YES_NO_OPTION);

if (respuesta == JOptionPane.YES_OPTION && unidades.remove(und)) {
guardarDatos();
return true;
}
else
return false;
}

/**
* Hace un recuento de cuantas Unidades tienen asignadas la
* Terminal indicada como argumento.<br>Cada Terminal solo puede
* tener hasta dos Unidades asignadas, así que antes de registrar
* una Unidad hay que controla esta limitación.
* @param nomTerminal Nombre de la Terminal a consultar.
* @return Cantidad de Unidades asignadas a la Terminal consultada.
*/
private int cuentaTerminalesAsignadas(String nomTerminal) {
int cont = 0;
for (Unidad und: unidades)
if (und.getNombreTerminal().equals(nomTerminal))
cont++;

return cont;
}

//TODO: metodo de generar placas y posible array para combobox

/**
* Construye una placa al azar y la retorna tras comprobar que es
* única.<br>Una placa se compone de tres consonantes y un número de
* tres dígitos.<br>Ejemplo: <i>[ABC000]</i>
* @return
*/
public String getPlaca() {
final char[] consonantes = {'B','C','D','F','G','H','J','K','L','M','N','P','Q','R','S',
'T','V','W','X','Y','Z'};
Random azar = new Random();
StringBuilder placa = new StringBuilder();
boolean esUnico = false;

while(!esUnico) {
//Primero obtenemos tres consonantes random
for (int i = 0; i < 3; i++)
placa.append(consonantes[azar.nextInt(consonantes.length)]);
//Y ahora un número de 3 dígitos, entre 000 y 999
placa.append(String.format("%03d", azar.nextInt(1000)));
//Comprobamos si existe alguna unidad con esta placa
esUnico = true;
for (Unidad und: unidades)
if (und.getPlaca().equals(placa.toString()))
esUnico = false; //Placa repetida, el bucle lo intentará de nuevo
}

return placa.toString();
}

public Unidad[] getArrayUnidades() {
return unidades.toArray(new Unidad[unidades.size()]);
}

}


Ahora habría que hacer la "vista", un panel para la gestión de Unidades, que al igual que el "modelo", será prácticamente copiar lo ya hecho para la gestión de Terminales, pero adaptado a la entidad/clase Unidad.
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

 

Sobre la educación, sólo puedo decir que es el tema más importante en el que nosotros, como pueblo, debemos involucrarnos.

Abraham Lincoln (1808-1865) Presidente estadounidense.

aprenderaprogramar.com: Desde 2006 comprometidos con la didáctica y divulgación de la programación

Preguntas y respuestas

¿Cómo establecer o cambiar la imagen asociada (avatar) de usuario?
  1. Inicia sesión con tu nombre de usuario y contraseña.
  2. Pulsa en perfil --> perfil del foro
  3. Elige la imagen personalizada que quieras usar. Puedes escogerla de una galería de imágenes o subirla desde tu ordenador.
  4. En la parte final de la página pulsa el botón "cambiar perfil".