Autor Tema: Relación entre Clases  (Leído 2794 veces)

jonij

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 8
    • Ver Perfil
Relación entre Clases
« en: 31 de Octubre 2023, 05:08 »
Hola buen día, estoy queriendo hacer un programa que simule una clínica en Java, haciendo uso de interfaz gráfica.

He definido algunas clases, como 'Paciente', 'Vacuna', 'Cita' y 'Expediente'.

Necesito que este programa permita las siguientes operaciones:

 - Gestión de pacientes: agregar, editar, mostrar y eliminar pacientes.
 - Gestión de vacunas: agregar vacunas a un paciente, editar vacunas de un paciente, mostrar las vacunas aplicadas de un paciente y eliminar vacunas aplicadas de un paciente.
 - Gestión de citas: crear citas a un paciente, editar citas de un paciente, mostrar las citas de un paciente y eliminar citas de un paciente.
 - Crear un expediente a un paciente: el expediente debe tomar la información del paciente su información (datos de la clase Paciente), sus vacunas, y permitir ingresar su diagnóstico, así como mostrar el expediente de un paciente.

Mi principal desafío radica en cómo relacionar estas clases para que puedan comunicarse entre sí y realizar las operaciones necesarias. Por ejemplo, ¿cómo puedo agregar vacunas a un paciente?, o ¿cómo puedo crearle un expediente a un paciente que tome su información y la de sus vacunas junto con su diagnóstico, y luego que permita ver el expediente del paciente?

Agradecería cualquier orientación que puedan ofrecerme.


Adjunto las clases que he creado hasta el momento.

Clase Paciente:

public class Paciente {

    private String numIdentificacionPaciente;
    private String nombrePaciente;
    private int edadPaciente;
    private String sexoPaciente;
    private double alturaPaciente;
    private double pesoPaciente;
    private String fechaNacPaciente;

    public Paciente() {
    }

    public Paciente(String numIdentificacionPaciente, String nombrePaciente, int edadPaciente, String sexoPaciente, double alturaPaciente, double pesoPaciente, String fechaNacPaciente) {
        this.numIdentificacionPaciente = numIdentificacionPaciente;
        this.nombrePaciente = nombrePaciente;
        this.edadPaciente = edadPaciente;
        this.sexoPaciente = sexoPaciente;
        this.alturaPaciente = alturaPaciente;
        this.pesoPaciente = pesoPaciente;
        this.fechaNacPaciente = fechaNacPaciente;
    }

    public String getNumIdentificacionPaciente() {
        return numIdentificacionPaciente;
    }

    public String getNombrePaciente() {
        return nombrePaciente;
    }

    public int getEdadPaciente() {
        return edadPaciente;
    }

    public String getSexoPaciente() {
        return sexoPaciente;
    }

    public double getAlturaPaciente() {
        return alturaPaciente;
    }

    public double getPesoPaciente() {
        return pesoPaciente;
    }

    public String getFechaNacPaciente() {
        return fechaNacPaciente;
    }

    public void setNumIdentificacionPaciente(String numIdentificacionPaciente) {
        this.numIdentificacionPaciente = numIdentificacionPaciente;
    }

    public void setNombrePaciente(String nombrePaciente) {
        this.nombrePaciente = nombrePaciente;
    }

    public void setEdadPaciente(int edadPaciente) {
        this.edadPaciente = edadPaciente;
    }

    public void setSexoPaciente(String sexoPaciente) {
        this.sexoPaciente = sexoPaciente;
    }

    public void setAlturaPaciente(double alturaPaciente) {
        this.alturaPaciente = alturaPaciente;
    }

    public void setPesoPaciente(double pesoPaciente) {
        this.pesoPaciente = pesoPaciente;
    }

    public void setFechaNacPaciente(String fechaNacPaciente) {
        this.fechaNacPaciente = fechaNacPaciente;
    }

    @Override
    public String toString() {
        return "Paciente{" + "numIdentificacionPaciente=" + numIdentificacionPaciente + ", nombrePaciente=" + nombrePaciente + ", edadPaciente=" + edadPaciente + ", sexoPaciente=" + sexoPaciente + ", alturaPaciente=" + alturaPaciente + ", pesoPaciente=" + pesoPaciente + ", fechaNacPaciente=" + fechaNacPaciente + '}';
    }
   
}


Clase PantallaPaciente:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.HashMap;

public class PantallaPaciente extends JFrame implements ActionListener {

    private JTextField txtNumIdentificacionPaciente;
    private JTextField txtNombrePaciente;
    private JTextField txtEdadPaciente;
    private JTextField txtSexoPaciente;
    private JTextField txtAlturaPaciente;
    private JTextField txtPesoPaciente;
    private JTextField txtFechaNacPaciente;
    private JTextArea txtResultado;
    private HashMap<String, Paciente> pacientes;

    public PantallaPaciente() {

        pacientes = new HashMap<>();

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(1000, 700);
        setLayout(new BorderLayout());
        setResizable(false);
        setLocationRelativeTo(null);

        JPanel panelFormulario = new JPanel(new GridLayout(5, 6, 10, 10));
        panelFormulario.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));

        JLabel lblNumIdentificacionPaciente = new JLabel("Número de Identificación del Paciente:");
        txtNumIdentificacionPaciente = new JTextField();

        JLabel lblNombrePaciente = new JLabel("Nombre del Paciente:");
        txtNombrePaciente = new JTextField();

 

        JLabel lblEdadPaciente = new JLabel("Edad del Paciente:");
        txtEdadPaciente = new JTextField();

       

        JLabel lblSexoPaciente = new JLabel("Sexo del Paciente:");
        txtSexoPaciente = new JTextField();

   

        JLabel lblAlturaPaciente = new JLabel("Altura del Paciente:");
        txtAlturaPaciente = new JTextField();

        JLabel lblPesoPaciente = new JLabel("Peso del Paciente:");
        txtPesoPaciente = new JTextField();


        JLabel lblFechaNacPaciente = new JLabel("Fecha de Nacimiento:");
        txtFechaNacPaciente = new JTextField();

        panelFormulario.add(lblNumIdentificacionPaciente);
        panelFormulario.add(txtNumIdentificacionPaciente);
        panelFormulario.add(lblNombrePaciente);
        panelFormulario.add(txtNombrePaciente);
        panelFormulario.add(lblEdadPaciente);
        panelFormulario.add(txtEdadPaciente);
        panelFormulario.add(lblSexoPaciente);
        panelFormulario.add(txtSexoPaciente);
        panelFormulario.add(lblAlturaPaciente);
        panelFormulario.add(txtAlturaPaciente);
        panelFormulario.add(lblPesoPaciente);
        panelFormulario.add(txtPesoPaciente);
        panelFormulario.add(lblFechaNacPaciente);
        panelFormulario.add(txtFechaNacPaciente);

        JButton btnAgregarPaciente = new JButton("Agregar");
        btnAgregarPaciente.addActionListener(this);

        JButton btnMostrarPacientes = new JButton("Mostrar");
        btnMostrarPacientes.addActionListener(this);

        JButton btnEditarPacientes = new JButton("Editar");
        btnEditarPacientes.addActionListener(this);

        JButton btnEliminarPaciente = new JButton("Eliminar");
        btnEliminarPaciente.addActionListener(this);

        JButton btnSalir = new JButton("Salir");
        btnSalir.addActionListener(this);

        panelFormulario.add(btnAgregarPaciente);
        panelFormulario.add(btnMostrarPacientes);
        panelFormulario.add(btnEditarPacientes);
        panelFormulario.add(btnEliminarPaciente);
        panelFormulario.add(btnSalir);

        txtResultado = new JTextArea();
        txtResultado.setEditable(false);
        JScrollPane scrollPane = new JScrollPane(txtResultado);
        scrollPane.setPreferredSize(new Dimension(560, 200));

        JPanel panelPrincipal = new JPanel(new BorderLayout());
        panelPrincipal.add(panelFormulario, BorderLayout.NORTH);
        panelPrincipal.add(scrollPane, BorderLayout.CENTER);
        panelPrincipal.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));

        add(panelPrincipal);
        setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getActionCommand().equals("Agregar")) {
            String numIdentificacionPaciente = txtNumIdentificacionPaciente.getText();
            String nombrePaciente = txtNombrePaciente.getText();
            String sexoPaciente = txtSexoPaciente.getText();
            String fechaNacPaciente = txtFechaNacPaciente.getText();
            String alturaPacienteStr = txtAlturaPaciente.getText();
            String pesoPacienteStr = txtPesoPaciente.getText();
            String edadPacienteStr = txtEdadPaciente.getText();

            if (!numIdentificacionPaciente.isEmpty() && !nombrePaciente.isEmpty()
                    && !fechaNacPaciente.isEmpty() && !alturaPacienteStr.isEmpty()
                    && !pesoPacienteStr.isEmpty() && !edadPacienteStr.isEmpty()) {
                try {
                    int edadPaciente = Integer.parseInt(edadPacienteStr);
                    double alturaPaciente = Double.parseDouble(alturaPacienteStr);
                    double pesoPaciente = Double.parseDouble(pesoPacienteStr);
                    Paciente nuevoPaciente = new Paciente(numIdentificacionPaciente, nombrePaciente,
                            edadPaciente, sexoPaciente,
                            alturaPaciente, pesoPaciente,fechaNacPaciente);

                    pacientes.put(numIdentificacionPaciente, nuevoPaciente);
                    txtResultado.setText("El paciente se ha añadido correctamente.");
                } catch (NumberFormatException ex) {
                    txtResultado.setText("Los valores numéricos o las fechas deben ser válidos.");
                }
            } else {
                txtResultado.setText("Por favor ingrese todos los datos requeridos.");
            }
        }
        if (e.getActionCommand().equals("Editar")) {
            String numIdentificacionPaciente = txtNumIdentificacionPaciente.getText();
            if (pacientes.containsKey(numIdentificacionPaciente)) {
                Paciente pacienteExistente = pacientes.get(numIdentificacionPaciente);
                pacienteExistente.setNombrePaciente(txtNombrePaciente.getText());
                pacienteExistente.setEdadPaciente(Integer.parseInt(txtEdadPaciente.getText()));
                pacienteExistente.setSexoPaciente(txtSexoPaciente.getText());
                pacienteExistente.setAlturaPaciente(Double.parseDouble(txtAlturaPaciente.getText()));
                pacienteExistente.setPesoPaciente(Double.parseDouble(txtPesoPaciente.getText()));
                pacienteExistente.setFechaNacPaciente(txtFechaNacPaciente.getText());

                txtResultado.setText("Los datos del paciente han sido actualizados.");
            } else {
                String nombrePaciente = txtNombrePaciente.getText();
                String sexoPaciente = txtSexoPaciente.getText();
                String fechaNacPaciente = txtFechaNacPaciente.getText();
                String alturaPacienteStr = txtAlturaPaciente.getText();
                String pesoPacienteStr = txtPesoPaciente.getText();
                String edadPacienteStr = txtEdadPaciente.getText();

                if (!numIdentificacionPaciente.isEmpty() && !nombrePaciente.isEmpty()
                        && !sexoPaciente.isEmpty() && !fechaNacPaciente.isEmpty()
                        && !alturaPacienteStr.isEmpty() && !pesoPacienteStr.isEmpty()
                        && !edadPacienteStr.isEmpty()) {
                    try {
                        int edadPaciente = Integer.parseInt(edadPacienteStr);
                        double alturaPaciente = Double.parseDouble(alturaPacienteStr);
                        double pesoPaciente = Double.parseDouble(pesoPacienteStr);
                        Paciente nuevoPaciente = new Paciente(numIdentificacionPaciente, nombrePaciente,
                                edadPaciente, sexoPaciente,
                                alturaPaciente, pesoPaciente,fechaNacPaciente);

                        pacientes.put(numIdentificacionPaciente, nuevoPaciente);
                        txtResultado.setText("El paciente se ha añadido correctamente.");
                    } catch (NumberFormatException ex) {
                        txtResultado.setText("Los valores numéricos o las fechas deben ser válidos.");
                    }
                } else {
                    txtResultado.setText("Por favor ingrese todos los datos requeridos.");
                }
            }
        } else if (e.getActionCommand().equals("Mostrar")) {
            txtResultado.setText("");
            if (pacientes.isEmpty()) {
                txtResultado.setText("No hay pacientes registrados.");
            } else {
                for (Paciente paciente : pacientes.values()) {
                    txtResultado.append(paciente.toString() + "\n");
                }
            }
        } else if (e.getActionCommand().equals("Eliminar")) {
            String numIdentificacionPaciente = txtNumIdentificacionPaciente.getText();
            if (pacientes.containsKey(numIdentificacionPaciente)) {
                pacientes.remove(numIdentificacionPaciente);
                txtResultado.setText("El paciente ha sido eliminado correctamente.");
            } else {
                txtResultado.setText("No se encontró un paciente con el número de identificación proporcionado.");
            }
        } else if (e.getActionCommand().equals("Salir")) {
            dispose();
        }
    }
}


Clase Vacuna:

public class Vacuna {

    private String numIdentificacionVacuna;
    private String fechaAplicacion;
    private String nombreVacuna;

    public Vacuna() {
    }

    public Vacuna(String numIdentificacionVacuna, String fechaAplicacion, String nombreVacuna) {
        this.numIdentificacionVacuna = numIdentificacionVacuna;
        this.fechaAplicacion = fechaAplicacion;
        this.nombreVacuna = nombreVacuna;
    }

    public String getNumIdentificacionVacuna() {
        return numIdentificacionVacuna;
    }

    public String getFechaAplicacion() {
        return fechaAplicacion;
    }

    public String getNombreVacuna() {
        return nombreVacuna;
    }

    public void setNumIdentificacionVacuna(String numIdentificacionVacuna) {
        this.numIdentificacionVacuna = numIdentificacionVacuna;
    }

    public void setFechaAplicacion(String fechaAplicacion) {
        this.fechaAplicacion = fechaAplicacion;
    }

    public void setNombreVacuna(String nombreVacuna) {
        this.nombreVacuna = nombreVacuna;
    }

   
    @Override
    public String toString() {
        return "Vacuna"
                + "  NumI dentificacion Vacuna: " + numIdentificacionVacuna + "\n"
                + "  Fecha de Aplicacion: " + fechaAplicacion + "\n"
                + "  Nombre Vacuna: " + nombreVacuna + "\n";
    }
}


Clase PantallaVacuna:

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

public class PantallaVacuna extends JFrame implements ActionListener {
    private JTextField txtNumIdentificacionPaciente;
    private JTextField txtNumIdentificacionVacuna;
    private JTextField txtFechaAplicacion;
    private JTextField txtNombreVacuna;
    private JTextArea txtResultado;

    public PantallaVacuna() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(800, 500);
        setLayout(new BorderLayout());
        setResizable(false);
        setLocationRelativeTo(null);

        JPanel panelFormulario = new JPanel(new GridLayout(4, 2, 10, 10));
        panelFormulario.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));

        JLabel lblNumIdentificacionPaciente = new JLabel("Número de Identificación del Paciente:");
        txtNumIdentificacionPaciente = new JTextField();

        JLabel lblNumIdentificacionVacuna = new JLabel("Número de Identificación de la Vacuna:");
        txtNumIdentificacionVacuna = new JTextField();

        JLabel lblFechaAplicacion = new JLabel("Fecha de Aplicación:");
        txtFechaAplicacion = new JTextField();

        JLabel lblNombreVacuna = new JLabel("Nombre de la Vacuna:");
        txtNombreVacuna = new JTextField();

       

        panelFormulario.add(lblNumIdentificacionPaciente);
        panelFormulario.add(txtNumIdentificacionPaciente);
        panelFormulario.add(lblNumIdentificacionVacuna);
        panelFormulario.add(txtNumIdentificacionVacuna);
        panelFormulario.add(lblFechaAplicacion);
        panelFormulario.add(txtFechaAplicacion);
        panelFormulario.add(lblNombreVacuna);
        panelFormulario.add(txtNombreVacuna);
     
        JButton btnAgregarVacuna = new JButton("Agregar Vacuna");
        btnAgregarVacuna.addActionListener(this);

        JButton btnMostrarVacunas = new JButton("Mostrar Vacunas");
        btnMostrarVacunas.addActionListener(this);

        JButton btnEliminarVacuna = new JButton("Eliminar Vacuna");
        btnEliminarVacuna.addActionListener(this);

        JButton btnSalir = new JButton("Salir");
        btnSalir.addActionListener(this);

        panelFormulario.add(btnAgregarVacuna);
        panelFormulario.add(btnMostrarVacunas);
        panelFormulario.add(btnEliminarVacuna);
        panelFormulario.add(btnSalir);

        txtResultado = new JTextArea();
        txtResultado.setEditable(false);
        JScrollPane scrollPane = new JScrollPane(txtResultado);
        scrollPane.setPreferredSize(new Dimension(560, 200));

        JPanel panelPrincipal = new JPanel(new BorderLayout());
        panelPrincipal.add(panelFormulario, BorderLayout.NORTH);
        panelPrincipal.add(scrollPane, BorderLayout.CENTER);
        panelPrincipal.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));

        add(panelPrincipal);
        setVisible(true);
    }

   

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getActionCommand().equals("Agregar Vacuna")) {
           
            String numIdentificacionPaciente = txtNumIdentificacionPaciente.getText();
            String numIdentificacionVacuna = txtNumIdentificacionVacuna.getText();
            String fechaAplicacion = txtFechaAplicacion.getText();
            String nombreVacuna = txtNombreVacuna.getText();
       
           
        } else if (e.getActionCommand().equals("Mostrar Vacunas")) {
           
            String numIdentificacionPaciente = txtNumIdentificacionPaciente.getText();
           
        } else if (e.getActionCommand().equals("Eliminar Vacuna")) {
           
            String numIdentificacionPaciente = txtNumIdentificacionPaciente.getText();
            String numIdentificacionVacuna = txtNumIdentificacionVacuna.getText();

        } else if (e.getActionCommand().equals("Salir")) {
            dispose();
        }
    }
}



Clase Cita:

public class Cita {

    private String numIdentificacionCita;
    private String fecha;
    private String hora;

}

Clase Expediente:

public class Expediente {

    private String numIdentificacionExpediente;
    private String diagnostico;

}


Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: Relación entre Clases
« Respuesta #1 en: 31 de Octubre 2023, 12:02 »
Puedes añadirle como atributo a Paciente, un ArrayList(u otro tipo de colección que tú prefieras) de clase Vacuna y así cada paciente tendrá su propia lista de las vacunas que se le han suministrado.
Citar
public class Paciente {

    private String numIdentificacionPaciente;
    private String nombrePaciente;
    private int edadPaciente;
    private String sexoPaciente;
    private double alturaPaciente;
    private double pesoPaciente;
    private String fechaNacPaciente;
    //Vacunas
    private ArrayList<Vacuna> vacunas;

    public Paciente() {
    }

    public Paciente(String numIdentificacionPaciente, String nombrePaciente, int edadPaciente, String sexoPaciente, double alturaPaciente, double pesoPaciente, String fechaNacPaciente) {
        this.numIdentificacionPaciente = numIdentificacionPaciente;
        this.nombrePaciente = nombrePaciente;
        this.edadPaciente = edadPaciente;
        this.sexoPaciente = sexoPaciente;
        this.alturaPaciente = alturaPaciente;
        this.pesoPaciente = pesoPaciente;
        this.fechaNacPaciente = fechaNacPaciente;
        vacunas = new ArrayList<Vacuna>();
    }


Luego habría que añadir los métodos correspondientes para actuar sobre ArrayList y poder añadir, consultar o eliminar vacunas.
El código de estos métodos puede depender de cómo vayas diseñando la interfaz y sus funcionalidades.

Dicho diseño tienes que replanteartelo.
Por ejemplo, la clase PantallaVacuna si quiere interactuar con los pacientes va a necesitar acceso al HashMap donde los almacenas, el cuál está declarado en la clase PantallaPaciente.

Hacer conexión entre estas dos "pantallas" es difícil, por no decir imposible, ya que no van a estar activas a la vez durante la ejecución del programa.
Es más, según tu código, si salimos de PantallaPaciente, al cerrarse este JFrame también desaparece el HashMap con los pacientes.
Por tanto, toda la información que se haya almacenado ahí, se perderá en cuanto queramos ir a gestionar vacunas, citas u otra cosa.

Es recomendable separar la parte gráfica (la "Vista") de la parte de los datos internos (el "Modelo") y ya luego se buscará forma de hacer conexión entre ellos (el "Controlador")

Lo ideal es que las aplicaciones tengan un único JFrame, un marco común para las distintas pantallas del programa y que se abre una vez al iniciar el programa y no se cierra hasta que finalizamos definitivamente la aplicación.
Este JFrame es quién puede servirnos de Controlador entre la Vista y el Modelo, ya que podemos ir diciéndole que cambie su contenido con distintos paneles y muestre/extraiga datos para comunicarlos al Modelo.


A ver si luego más tarde encuentro tiempo y te muestro un ejemplo de como organizar esto
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

jonij

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 8
    • Ver Perfil
Re: Relación entre Clases
« Respuesta #2 en: 31 de Octubre 2023, 17:07 »
Hola Kabuto, aprecio que te hayas tomado el tiempo para revisar mi código y ofrecer orientación, tienes razón en que el código necesita ser replanteado. Estaré pendiente de cualquier ejemplo o recomendación que puedas proporcionarme mas tarde.

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: Relación entre Clases
« Respuesta #3 en: 01 de Noviembre 2023, 11:02 »
Bueno. Ya tengo una mínima parte hecha que pueda servir de ejemplo/inspiración.

Lo primero que quiero mostrar es cómo he distribuido los packages.
Esta distribución no es obligatoria ni tampoco los nombres que le he puesto a los packages. De hecho no creo que ningún profesional lo haga así.



Pero viene bien para propósitos didácticos, refleja muy bien la aplicación del patrón MVC(Modelo-Vista-Controlador).
Un "patrón" es una forma de organizar el código, el más habitual es el MVC porque es el más sencillo y sirve para prácticamente cualquier proyecto sea cuál sea su propósito.

En el paquete llamado "modelo" es donde escribiríamos las clases que se encargan de las entidades que "no vemos": Pacientes, Citas, Expedientes,Vacunas,....
Y también las clases que se encarguen de trabajar con estas entidades. Ahí junto a la clase Paciente, podemos ver otra clase llamada GestorPaciente.
Esta clase "gestora" será la que contenga el HashMap con los pacientes y los métodos necesarios para añadir, buscar, eliminar o lo que se nesecite.

En el paquete llamado "vista" es donde codificaremos las clases que representan las entidades que "sí vemos". Es decir, los elementos gráficos que van a componer la interfaz.
Ahí escribiremos las "pantallas" para mostrar los datos de Pacientes, Vacunas, Citas....
Estas "pantallas" serán clases JPanel, ya que como dije anteriormente, lo correcto es que solo exista un único JFrame para toda la aplicación.
Ahí en el paquete "vista", también de podrían escribir otras clases que pudiéramos necesitar para componer la interfaz.
Si por ejemplo quisiéramos diseñar un botón con un tamaño, color y fuente concretos, y que además pudiéramos usar ese diseño para todos los botones de la interfaz, pues podríamos crear una clase JButton con el diseño que nos guste y así poder usarlo en distintos paneles.

Bueno, tenemos el paquete "modelo", el paquete "vista" y por último el paquete "controlador".
Aquí es donde vamos a tener la clase principal, que será el JFrame y entre sus atributos tendrá objetos del "modelo" y también de la "vista".
De esta forma, el "controlador" hace de nexo entre esas dos partes y permite que interactúen entre ellas a pesar de que se han escrito por separado.

Veamos, el código que he podido escribir. Empecemos por la parte del "modelo".

Tenemos la clase Paciente, que es la que tú escribiste pero con el añadido de un ArrayList para guardar las vacunas que se le apliquen a este paciente.
Ahora mismo este ArrayList no está usándose, y de hecho, puede que luego surja un cambio de opinión y no se le de uso.
Pues otra posible forma de asociar pacientes con vacunas es crear una única colección (en otra clase fuera de Paciente) que contenga un identificador de paciente y el objeto Vacuna asociado.
Es decir, tendríamos dos propuestas:
1) Cada paciente tiene su propia lista de vacunas
2) Habrá una única lista donde se asociarán identificadores de pacientes y vacunas.

Ambas son válidas, elegir una u otra es cuestión de gustos y también puede depender de lo que queramos hacer y mostrar en la "pantalla" para las vacunas.

Por ahora, el código de Paciente es este:
Código: [Seleccionar]
public class Paciente {

    private String numIdentificacionPaciente;
    private String nombrePaciente;
    private int edadPaciente;
    private String sexoPaciente;
    private double alturaPaciente;
    private double pesoPaciente;
    private String fechaNacPaciente;
    //Vacunas
    private ArrayList<Vacuna> vacunas; //Provisional, sin funcionalidad actualmente

    public Paciente() {
    }

    public Paciente(String numIdentificacionPaciente, String nombrePaciente, int edadPaciente, String sexoPaciente, double alturaPaciente, double pesoPaciente, String fechaNacPaciente) {
        this.numIdentificacionPaciente = numIdentificacionPaciente;
        this.nombrePaciente = nombrePaciente;
        this.edadPaciente = edadPaciente;
        this.sexoPaciente = sexoPaciente;
        this.alturaPaciente = alturaPaciente;
        this.pesoPaciente = pesoPaciente;
        this.fechaNacPaciente = fechaNacPaciente;
        vacunas = new ArrayList<Vacuna>();
    }

    public String getNumIdentificacionPaciente() {
        return numIdentificacionPaciente;
    }

    public String getNombrePaciente() {
        return nombrePaciente;
    }

    public int getEdadPaciente() {
        return edadPaciente;
    }

    public String getSexoPaciente() {
        return sexoPaciente;
    }

    public double getAlturaPaciente() {
        return alturaPaciente;
    }

    public double getPesoPaciente() {
        return pesoPaciente;
    }

    public String getFechaNacPaciente() {
        return fechaNacPaciente;
    }

    public void setNumIdentificacionPaciente(String numIdentificacionPaciente) {
        this.numIdentificacionPaciente = numIdentificacionPaciente;
    }

    public void setNombrePaciente(String nombrePaciente) {
        this.nombrePaciente = nombrePaciente;
    }

    public void setEdadPaciente(int edadPaciente) {
        this.edadPaciente = edadPaciente;
    }

    public void setSexoPaciente(String sexoPaciente) {
        this.sexoPaciente = sexoPaciente;
    }

    public void setAlturaPaciente(double alturaPaciente) {
        this.alturaPaciente = alturaPaciente;
    }

    public void setPesoPaciente(double pesoPaciente) {
        this.pesoPaciente = pesoPaciente;
    }

    public void setFechaNacPaciente(String fechaNacPaciente) {
        this.fechaNacPaciente = fechaNacPaciente;
    }

    @Override
    public String toString() {
        return "Paciente{" + "numIdentificacionPaciente=" + numIdentificacionPaciente + ", nombrePaciente=" + nombrePaciente + ", edadPaciente=" + edadPaciente + ", sexoPaciente=" + sexoPaciente + ", alturaPaciente=" + alturaPaciente + ", pesoPaciente=" + pesoPaciente + ", fechaNacPaciente=" + fechaNacPaciente + '}';
    }
   
}

Luego tenemos la clase GestorPacientes, que como dije antes, alberga y gestiona un HashMap de tipo Paciente
Código: [Seleccionar]
public class GestorPacientes {

private HashMap<String, Paciente> pacientes = new HashMap<>();

public void agregarPaciente(Paciente paci) {
pacientes.put(paci.getNumIdentificacionPaciente(), paci);
}

public void modificarPaciente(Paciente paci) {
if (pacientes.containsKey(paci.getNumIdentificacionPaciente())) {
int respuesta = JOptionPane.showConfirmDialog(null,
"¿Modificar paciente?", "Modificar", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION) {
pacientes.replace(paci.getNumIdentificacionPaciente(), paci);
JOptionPane.showMessageDialog(null, "Paciente modificado");
}
}
}

public boolean borrarPaciente(String id) {
if (pacientes.containsKey(id)) {
int respuesta = JOptionPane.showConfirmDialog(null,
"¿Eliminar paciente?", "Eliminar", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION) {
pacientes.remove(id);
JOptionPane.showMessageDialog(null, "Paciente eliminado");
return true;
}
}
else
JOptionPane.showMessageDialog(null, "No existe paciente con ese identificador.");

return false;
}

public Paciente getPaciente(String id) {
if (pacientes.containsKey(id))
return pacientes.get(id);
else {
JOptionPane.showMessageDialog(null, "No existe paciente con ese identificador.");
return null;
}
}

public String[] getListaId() {
String[] lista = new String[pacientes.size()];
int i = 0;
for (Entry<String, Paciente> entry : pacientes.entrySet()) {
lista[i] = entry.getKey();
i++;
}

return lista;
}

}
Entre sus métodos para añadir, modificar y eliminar pacientes, vemos también uno que genera un array con la lista de identificadores de los pacientes registrados.
Esto nos será útil para luego mostrar estos identificadores en la pantalla y que el usuario pueda seleccionarlos y consultar sus datos.
Hay otro método que nos retorna un Paciente, según el identificador que le proporcionemos.

Por último está la clase Vacuna, que es exactamente igual a la tuya, no he hecho nada con ella.
Código: [Seleccionar]
public class Vacuna {

    private String numIdentificacionVacuna;
    private String fechaAplicacion;
    private String nombreVacuna;

    public Vacuna() {
    }

    public Vacuna(String numIdentificacionVacuna, String fechaAplicacion, String nombreVacuna) {
        this.numIdentificacionVacuna = numIdentificacionVacuna;
        this.fechaAplicacion = fechaAplicacion;
        this.nombreVacuna = nombreVacuna;
    }

    public String getNumIdentificacionVacuna() {
        return numIdentificacionVacuna;
    }

    public String getFechaAplicacion() {
        return fechaAplicacion;
    }

    public String getNombreVacuna() {
        return nombreVacuna;
    }

    public void setNumIdentificacionVacuna(String numIdentificacionVacuna) {
        this.numIdentificacionVacuna = numIdentificacionVacuna;
    }

    public void setFechaAplicacion(String fechaAplicacion) {
        this.fechaAplicacion = fechaAplicacion;
    }

    public void setNombreVacuna(String nombreVacuna) {
        this.nombreVacuna = nombreVacuna;
    }

   
    @Override
    public String toString() {
        return "Vacuna"
                + "  NumI dentificacion Vacuna: " + numIdentificacionVacuna + "\n"
                + "  Fecha de Aplicacion: " + fechaAplicacion + "\n"
                + "  Nombre Vacuna: " + nombreVacuna + "\n";
    }
}

En el siguiente post vemos la parte de la "vista".
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: Relación entre Clases
« Respuesta #4 en: 01 de Noviembre 2023, 11:38 »
La "vista".
Tengo la clase PantallaPaciente que como dije, será un JPanel que insertaremos en el JFrame principal.
Usa campos de texto para mostrar/recoger los datos de los pacientes, a excepción del "identificador".
Este valor se muestra en una caja desplegable (JComboBox) y así el usuario puede ir seleccionando identificadores y mostrar los datos en pantalla.
A la hora de crear un nuevo paciente, el usuario no proporciona el identificador. He hecho que este valor se genere automáticamente dando formato a un String que acaba en un valor numérico. Este valor numérico se calcula según la cantidad de pacientes registrados, así siempre es distinto y además correlativos.

Tenemos además 4 botones: Agregar(paciente), Modificar, Eliminar y otro para borrar los campos del formulario.

Para que estos botones puedan ejercer sus funciones, se necesita acceso al objeto que se encargará de gestionar los pacientes.
Este objeto, como luego veremos, será declarado en la clase principal(el JFrame) así que, para que esta "pantalla" tenga acceso a ese objeto GestorPacientes, entre sus atributos vamos a poner un objeto de ese tipo y le haremos llegar una referencia por el constructor.
Así la "pantalla" de pacientes y el "gestor" de pacientes, estarán comunicados.

Esta clase tiene bastante código. Hay varios comentarios dando explicaciones, pero si necesitas más, no dudes en preguntar.
Código: [Seleccionar]
public class PantallaPaciente extends JPanel {

private JComboBox<String> listaId;
private JTextField jtNombre;
private JTextField jtEdad;
private JTextField jtSexo;
private JTextField jtAltura;
private JTextField jtPeso;
private JTextField jtFecha;
private JButton btAgregar;
private JButton btModificar;
private JButton btBorrar;
private JButton btReset;
//Referencia al gestor de pacientes
private GestorPacientes pacientes;

public PantallaPaciente(GestorPacientes pacientes) {
this.pacientes = pacientes;
listaId = new JComboBox<String>(pacientes.getListaId());
listaId.setPrototypeDisplayValue("XXXXXXX");
listaId.addItemListener(new AccionLista());
jtNombre = new JTextField(12);
jtEdad = new JTextField(6);
jtSexo = new JTextField(6);
jtAltura = new JTextField(6);
jtPeso = new JTextField(6);
jtFecha = new JTextField(12);
btAgregar = new JButton("Agregar");
btAgregar.addActionListener(new AccionAgregar());
btModificar = new JButton("Modificar");
btModificar.addActionListener(new AccionModificar());
btBorrar = new JButton("Eliminar");
btBorrar.addActionListener(new AccionBorrar());
btReset = new JButton("Borrar campos");
btReset.addActionListener(new AccionReset());

setLayout(new BorderLayout());

JPanel pnNorte = new JPanel();
JLabel lbTitulo = new JLabel("GESTION PACIENTES");
lbTitulo.setFont(new Font("Verdana",Font.BOLD, 24));
pnNorte.add(lbTitulo);
pnNorte.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(10,10,10,10),
BorderFactory.createRaisedSoftBevelBorder()));

JPanel pnCentro = new JPanel();
pnCentro.setLayout(new BoxLayout(pnCentro, BoxLayout.Y_AXIS));

JPanel pnGrilla = new JPanel();
pnGrilla.setLayout(new GridLayout(3,2,5,5));
pnGrilla.add(new PanelConLabel("Ident: ", listaId));
pnGrilla.add(new PanelConLabel("Nombre: ", jtNombre));
pnGrilla.add(new PanelConLabel("Edad: ", jtEdad));
pnGrilla.add(new PanelConLabel("Sexo: ", jtSexo));
pnGrilla.add(new PanelConLabel("Altura: ", jtAltura));
pnGrilla.add(new PanelConLabel("Peso: ", jtPeso));

JPanel pnFecha = new JPanel();
pnFecha.add(new PanelConLabel("Fecha Nacimiento: ", jtFecha));

pnCentro.add(pnGrilla);
pnCentro.add(pnFecha);
pnCentro.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(10,10,10,10),
BorderFactory.createEtchedBorder(EtchedBorder.LOWERED)));

JPanel pnSur = new JPanel();
pnSur.setLayout(new FlowLayout(FlowLayout.CENTER, 15, 5));
pnSur.add(btAgregar);
pnSur.add(btModificar);
pnSur.add(btBorrar);
pnSur.add(btReset);

add(pnNorte, BorderLayout.NORTH);
add(pnCentro, BorderLayout.CENTER);
add(pnSur, BorderLayout.SOUTH);

setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));

}

//Clase JPanel para maquetar un elemento de la interfaz junto una etiqueta
private class PanelConLabel extends JPanel {
public PanelConLabel(String texto, JComponent componente) {
add(new JLabel(texto));
add(componente);
}
}

//Metodo para limpiar formulario
private void resetFormulario() {
jtNombre.setText(null);
jtEdad.setText(null);
jtSexo.setText(null);
jtAltura.setText(null);
jtPeso.setText(null);
jtFecha.setText(null);
listaId.setSelectedIndex(-1);
}

//Metodo para poder lanzar distintas alertas
private void alerta(String mensaje) {
JOptionPane.showMessageDialog(null, mensaje, "Aviso", JOptionPane.WARNING_MESSAGE);
}

//Metodo para validar campos y crear un Paciente con ellos
private Paciente validarCampos() {

String nombre = jtNombre.getText();
if (jtNombre.getText().isBlank()) {
alerta("Campo NOMBRE es obligatorio");
return null;
}

String txtEdad = jtEdad.getText();
if (txtEdad.isBlank()) {
alerta("Campo EDAD es obligatorio");
return null;
}

String sexo = jtSexo.getText();
if (sexo.isBlank()) {
alerta("Campo SEXO es obligatorio");
return null;
}

String txtAltura = jtAltura.getText();
if (txtAltura.isBlank()) {
alerta("Campo ALTURA es obligatorio");
return null;
}

String txtPeso = jtPeso.getText();
if (txtPeso.isBlank()) {
alerta("Campo PESO es obligatorio");
return null;
}

String fecha = jtFecha.getText();
if (fecha.isBlank()) {
alerta("Campo FECHA NACIMIENTO es obligatorio");
return null;
}

//Intentamos parsear los valores numéricos
int edad;
double altura, peso;
try {
edad = Integer.parseInt(txtEdad);
altura = Double.parseDouble(txtAltura);
peso = Double.parseDouble(txtPeso);
}
catch(Exception ex) {
alerta("Introduza solo valores numéricos en los campos correspondientes");
return null;
}

//Retornamos un paciente, que aún no tendrá un identificador definido
return new Paciente(null, nombre, edad, sexo, altura, peso, fecha);
}

//Clases Listener
private class AccionLista implements ItemListener {
//Detecta que id de la lista se ha seleccionado y muestra los datos de ese paciente
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == 1) { //Se ha seleccionado un item en la lista
String id = (String) e.getItem(); //Capturamos id seleccionado
Paciente elegido = pacientes.getPaciente(id); //Buscamos paciente con ese id

if (elegido != null) {//Actualizamos interfaz
jtNombre.setText(elegido.getNombrePaciente());
jtEdad.setText(Integer.toString(elegido.getEdadPaciente()));
jtSexo.setText(elegido.getSexoPaciente());
jtAltura.setText(Double.toString(elegido.getAlturaPaciente()));
jtPeso.setText(Double.toString(elegido.getPesoPaciente()));
jtFecha.setText(elegido.getFechaNacPaciente());
}
}
}

}

private class AccionAgregar implements ActionListener {
//Registra un nuevo paciente con los datos validados del formulario
@Override
public void actionPerformed(ActionEvent e) {
Paciente nuevo = validarCampos();
if (nuevo != null) {
/*
* El identificador lo generamos automáticamente dando formato a un String
* que varía según pacientes registrados.
* Nos dará identificadores como : PAC0000, PAC0001, PAC0002,....
* y así sucesivamente.
* De este modo garantizamos un formato único para el identificador y se minimiza
* la posibilidad de que se dupliquen
*/
String ident = String.format("PAC%04d", pacientes.getListaId().length);
nuevo.setNumIdentificacionPaciente(ident);
//Guardamos paciente
pacientes.agregarPaciente(nuevo);
//Actualizamos combobox con la lista de identificadores
listaId.addItem(ident);
listaId.setSelectedItem(ident);
}
}
}

private class AccionModificar implements ActionListener {
//Modifica el Paciente actualmente seleccionado
@Override
public void actionPerformed(ActionEvent e) {
Paciente modificar = validarCampos();

if (modificar != null) {
String id = (String) listaId.getSelectedItem();
modificar.setNumIdentificacionPaciente(id);
pacientes.modificarPaciente(modificar);
}
}
}

private class AccionBorrar implements ActionListener {
//Elimina el Paciente actualmente seleccionado
@Override
public void actionPerformed(ActionEvent e) {
String id = (String) listaId.getSelectedItem();
if (pacientes.borrarPaciente(id)) {
listaId.removeItem(id);
resetFormulario();
}
}
}

private class AccionReset implements ActionListener {
//Borra los valores de los campos del formulario
@Override
public void actionPerformed(ActionEvent e) {
resetFormulario();
}
}

}

Luego tenemos la clase PantallaVacuna.
Este panel está por construir, muestra simplemente un "título".
Lo he creado para que luego pueda verse cómo podemos ir de una "pantalla" a otra dentro del mismo JFrame.

Código: [Seleccionar]
public class PantallaVacuna extends JPanel {

public PantallaVacuna() {

setLayout(new BorderLayout());

JPanel pnNorte = new JPanel();
JLabel lbTitulo = new JLabel("GESTION VACUNAS");
lbTitulo.setFont(new Font("Verdana",Font.BOLD, 24));
pnNorte.add(lbTitulo);
pnNorte.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(10,10,10,10),
BorderFactory.createRaisedSoftBevelBorder()));

add(pnNorte, BorderLayout.NORTH);
}

}


Pues ya podemos ir a ver la parte del "controlador", que va a consistir únicamente en la clase principal.
Esta clase es un JFrame donde, mediante un menú de botones en la parte superior, podremos elegir la "pantalla" a la que queremos ir.

Para poder alternar entre una "pantalla" u otra, aplicaremos un CardLayout.
Este "layout" permite apilar varios paneles como si fuera un "mazo de cartas".
Es decir, están unos sobre otros y solo se ve el primero, el que está en lo alto del "mazo".
Con la barra de menú, vamos a elegir cuál panel será el que esté primero en cada momento y así podemos alternar entre las distintas "pantallas"




En los atributos de la clase principal JFrame, iremos declarando las distintas "pantallas" y los distintos "gestores" (en caso de haberlos). Así "modelo" y "vista" tendrán un marco común donde poder comunicarse en caso necesario.

El CardLayout también conviene declararlo como atributo de clase para que sea accesible a los botones del menú que alternarán las "pantallas".

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

private GestorPacientes gestorPacientes = new GestorPacientes();

private PantallaPaciente pantallaPaciente = new PantallaPaciente(gestorPacientes);
private PantallaVacuna pantallaVacuna = new PantallaVacuna();

private CardLayout paneles = new CardLayout();

public Clinica() {

setLayout(paneles);
add(pantallaPaciente, "Pacientes");
add(pantallaVacuna, "Vacunas");

JMenuItem itemPaciente = new JMenuItem("Pacientes");
itemPaciente.addActionListener(e -> gestionarPacientes());//Expresion lambda
        JMenuItem itemVacuna = new JMenuItem("Vacunas");
        itemVacuna.addActionListener(e -> gestionarVacunas());//Expresion lambda
        JMenuItem itemCitas = new JMenuItem("Citas");
        itemCitas.addActionListener(e -> gestionarCitas());//Expresion lambda
        JMenuItem itemExped = new JMenuItem("Expedientes");
        itemExped.addActionListener(e -> gestionarExpedientes());//Expresion lambda
        JMenu menu = new JMenu("Gestionar");
        menu.add(itemPaciente);
        menu.add(itemVacuna);
        menu.addSeparator();
        menu.add(itemCitas);
        menu.add(itemExped);
        JMenuBar menuBarra = new JMenuBar();
        menuBarra.add(menu);
        setJMenuBar(menuBarra);

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

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

private void gestionarPacientes() {
paneles.show(getContentPane(), "Pacientes");
}
private void gestionarVacunas() {
paneles.show(getContentPane(), "Vacunas");
}
private void gestionarCitas() {
JOptionPane.showMessageDialog(null, "Pantalla aún no construida");
}
private void gestionarExpedientes() {
JOptionPane.showMessageDialog(null, "Pantalla aún no construida");
}
}

Y bueno, todo esto puede servir como punto de partida para seguir construyendo la aplicación y organizarla como hemos visto, o bien de forma similar.

El siguiente paso será decidir que se va a mostrar y que va a pasar en la "pantalla" de vacunas, y en función de eso, decidir si conviene que cada paciente tenga su propia lista de vacunas, o hacer una única lista general para todos los pacientes.

Intenta continuar a partir de aquí, a ver que se te ocurre.
Y no dudes en preguntar lo que no entiendas del código que he escrito.

Por cierto, adjunto mi código en este mensaje comprimido en un zip.

Si tengo ocasión de seguir avanzando algo más, lo comparto por aquí y así podemos comparar nuestros avances.

Un saludo
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

jonij

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 8
    • Ver Perfil
Re: Relación entre Clases
« Respuesta #5 en: 01 de Noviembre 2023, 19:08 »
Buen día, me parece muy bien, para la pantalla vacuna quiero poder agregarle varias vacunas (una a la vez, así como ir agregando los pacientes) a un determinado paciente. Así como también editarlas y eliminarlas.

Luego poder ver las todas las vacunas que tiene aplicadas un determinado paciente.

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: Relación entre Clases
« Respuesta #6 en: 03 de Noviembre 2023, 11:56 »
Podemos hacer algo muy parecido a como hemos gestionado los Pacientes.

En la "pantalla" de vacunas tendremos un selector para elegir Paciente. Y cada vez que elijamos uno, se actualizará otro selector con la lista de vacunas de ese paciente "elegido".
Esto permitirá ir seleccionado vacunas de esa lista y ya podremos modificar, eliminar o agregar nuevas



Bien, para hacer esto. Primero he hecho algunos cambios en el código anterior.

Para crear PantallaPacientes usamos un pequeña clase privada interna que creaba un pequeño panel asociando un Jlabel con otro componente de la interfaz para conseguir una maquetación medio decente.
Puesto que también será útil para crear otras pantalla, lo he extraído de PantallaPacientes para que sea una clase pública independiente y así poder llamarla desde otras clases si la necesitamos
Código: [Seleccionar]
//Clase JPanel para maquetar un elemento de la interfaz junto una etiqueta
public class PanelConLabel extends JPanel {
public PanelConLabel(String texto, JComponent componente) {

add(new JLabel(texto));
add(componente);
}
}

Luego, para no tener que estar creando una y otra vez a nuevos pacientes cada vez que hacemos un cambio en el programa y queremos comprobar si funciona, le he añadido un constructor a la clase GestorPacientes(antes no tenía) con código para crear 4 pacientes con algunas vacunas ya en su historial.
Así siempre que reiniciamos la aplicación tendremos contenido para hacer pruebas

Citar
public class GestorPacientes {
   
   private HashMap<String, Paciente> pacientes = new HashMap<>();
   
   public GestorPacientes() {
      //Constructor con el único propósito de añadir pacientes de prueba
      Paciente pac1 = new Paciente(String.format("PAC%04d", pacientes.size()), "Juan Reinas", 35,
            "Hombre", 1.78, 80, "22/11/1986");
      pac1.agregarVacuna("10/08/2011", "BEXSERO");
      pac1.agregarVacuna("10/08/2020", "SPIKEVAX");
      pacientes.put(pac1.getNumIdentificacionPaciente(), pac1);
      Paciente pac2 = new Paciente(String.format("PAC%04d", pacientes.size()), "Sara Hidalgo", 24,
            "Mujer", 1.66, 65, "11/02/1995");
      pac2.agregarVacuna("05/03/2021", "CERVARIX");
      pac2.agregarVacuna("10/08/2022", "DUKORAL");
      pacientes.put(pac2.getNumIdentificacionPaciente(), pac2);
      Paciente pac3 = new Paciente(String.format("PAC%04d", pacientes.size()), "Andrés Trasado", 27,
            "Hombre", 1.72, 76, "07/03/1989");
      pacientes.put(pac3.getNumIdentificacionPaciente(), pac3);
      Paciente pac4 = new Paciente(String.format("PAC%04d", pacientes.size()), "Carmen Soler", 55,
            "Mujer", 1.62, 58, "24/09/1972");
      pac4.agregarVacuna("15/08/2016", "GARDASIL 9");
      pacientes.put(pac4.getNumIdentificacionPaciente(), pac4);
   }


Bien, respecto a las Vacunas. Finalmente me he decantado por hacer que cada Paciente tenga su propia lista de vacunas.
Ya dejamos añadido un ArrayList de Vacunas en la clase Paciente pero sin darle uso.

Ahora sí vamos a darle uso. A la clase Paciente le vamos a añadir varios métodos para que actúen en ese ArrayList
Código: [Seleccionar]
/*
     * Agrega una vacuna y retorna el id que se le ha asigando.
     * Este retorno es útil para actualizar en pantalla el listado
     * de identificadores de vacunas
     */
    public String agregarVacuna(String fecha, String nombre) {
    String id = String.format("VAC%04d", vacunas.size());
    Vacuna vac = new Vacuna(id, fecha, nombre);
    vacunas.add(vac);
    return id;
    }
   
    /*
     * Modifica una vacuna cambiando fecha y nombre, no el identificador
     */
    public void modificarVacuna(Vacuna vac) {
    for (Vacuna v: vacunas)
    if (v.getNumIdentificacionVacuna().equals(vac.getNumIdentificacionVacuna())) {
    v.setNombreVacuna(vac.getNombreVacuna());
    v.setFechaAplicacion(vac.getFechaAplicacion());
    break;
    }
    }
   
    /*
     * Elimina la vacuna que coincida con el identificador indicado.
     */
    public void eliminarVacuna(String id) {
    int indice = 0;
    for (int i = 0; i < vacunas.size(); i++)
    if (vacunas.get(i).getNumIdentificacionVacuna().equals(id)) {
    indice = i;
    break;
    }
   
    vacunas.remove(indice);
    }
   
    /*
     * Retorna la vacuna que coincida con el identificador indicado
     */
    public Vacuna getVacuna(String id) {
    Vacuna buscar = null;
    for (Vacuna v: vacunas)
    if (v.getNumIdentificacionVacuna().equals(id)) {
    buscar = v;
    break;
    }
   
    return buscar;
    }
   
    /*
     * Crea un array con la lista de identificadores de vacunas.
     * Es necesario para actualizar el selector JComboBox en la
     * "pantalla" de vacunas.
     */
    public String[] getListaIdVacunas() {
    String[] lista = new String[vacunas.size()];
    for (int i = 0; i < vacunas.size(); i++)
    lista[i] = vacunas.get(i).getNumIdentificacionVacuna();
   
    return lista;
    }


Hecho esto, podemos crear la clase PantallaVacuna.
Es muy similar a la de los pacientes, solo que se puede ver en la imagen que puse al principio, ahora tendremos dos JComboBox, uno para elegir pacientes y otro para elegir vacunas del paciente "elegido".

El paciente "elegido" es importante, pues habrá que actuar sobre él para consultar y modificar su historial de vacunas.
Así que para tenerlo siempre a mano y visible en todo el ámbito de esta clase, lo vamos a poner como un atributo y su valor irá cambiando cada vez que escogemos un elemento del JComboBox de pacientes.

Código: [Seleccionar]
public class PantallaVacuna extends JPanel {

private JComboBox<String> listaPacientes;
private JTextField jtPaci;
private JComboBox<String> listaVacunas;
private JTextField jtNombre;
private JTextField jtFecha;
private JButton btAgregar;
private JButton btModificar;
private JButton btBorrar;
private JButton btReset;
private GestorPacientes pacientes;
private Paciente elegido; //Referencia al paciente que está seleccionado actualmente

public PantallaVacuna(GestorPacientes pacientes) {

this.pacientes = pacientes;
listaPacientes = new JComboBox<String>(pacientes.getListaId());
listaPacientes.setPrototypeDisplayValue("XXXXXXX");
listaPacientes.addItemListener(new AccionListaPaci());
listaVacunas = new JComboBox<String>();
listaVacunas.setPrototypeDisplayValue("XXXXXXX");
listaVacunas.addItemListener(new AccionListaVac());
jtPaci = new JTextField(12);
jtPaci.setEditable(false);
jtNombre = new JTextField(12);
jtFecha = new JTextField(12);
btAgregar = new JButton("Agregar");
btAgregar.addActionListener(new AccionAgregar());
btModificar = new JButton("Modificar");
btModificar.addActionListener(new AccionModificar());
btBorrar = new JButton("Eliminar");
btBorrar.addActionListener(new AccionBorrar());
btReset = new JButton("Borrar campos");
btReset.addActionListener(new AccionReset());

setLayout(new BorderLayout());

JPanel pnNorte = new JPanel();
JLabel lbTitulo = new JLabel("GESTION VACUNAS");
lbTitulo.setFont(new Font("Verdana",Font.BOLD, 24));
pnNorte.add(lbTitulo);
pnNorte.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(10,10,10,10),
BorderFactory.createRaisedSoftBevelBorder()));

JPanel pnCentro = new JPanel();
pnCentro.setLayout(new BoxLayout(pnCentro, BoxLayout.Y_AXIS));

JPanel pnElegirPaci = new JPanel();
pnElegirPaci.add(new PanelConLabel("Elija Paciente: ", listaPacientes));
pnElegirPaci.add(jtPaci);

pnElegirPaci.setBorder(BorderFactory.createTitledBorder("Pacientes"));

JPanel pnElegirVacu = new JPanel();
pnElegirVacu.setLayout(new BoxLayout(pnElegirVacu, BoxLayout.Y_AXIS));
pnElegirVacu.add(new PanelConLabel("Elija Vacuna: ", listaVacunas));

JPanel pnVacuna = new JPanel();
pnVacuna.setLayout(new BoxLayout(pnVacuna, BoxLayout.Y_AXIS));
pnVacuna.add(new PanelConLabel("Nombre: ", jtNombre));
pnVacuna.add(new PanelConLabel("Fecha Aplicacion: ", jtFecha));
pnElegirVacu.add(pnVacuna);
pnElegirVacu.setBorder(BorderFactory.createTitledBorder("Vacunas"));

pnCentro.add(pnElegirPaci);
pnCentro.add(pnElegirVacu);

JPanel pnSur = new JPanel();
pnSur.setLayout(new FlowLayout(FlowLayout.CENTER, 15, 5));
pnSur.add(btAgregar);
pnSur.add(btModificar);
pnSur.add(btBorrar);
pnSur.add(btReset);

add(pnNorte, BorderLayout.NORTH);
add(pnCentro, BorderLayout.CENTER);
add(pnSur, BorderLayout.SOUTH);

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


//Metodo para limpiar formulario y actualizar lista de pacientes
public void resetFormulario() {
listaPacientes.removeAllItems();
for (String item: pacientes.getListaId())
listaPacientes.addItem(item);
listaPacientes.setSelectedIndex(-1);
jtPaci.setText(null);
listaVacunas.removeAllItems();
jtNombre.setText(null);
jtFecha.setText(null);
}

//Metodo para poder lanzar distintas alertas
private void alerta(String mensaje) {
JOptionPane.showMessageDialog(null, mensaje, "Aviso", JOptionPane.WARNING_MESSAGE);
}

//Clases Listener
private class AccionListaPaci implements ItemListener {
//Detecta que id de la lista se ha seleccionado y muestra los datos de ese paciente
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == 1) { //Se ha elegido un paciente, lo buscamos
String id = (String) e.getItem();
elegido = pacientes.getPaciente(id);
//Mostramos su nombre
jtPaci.setText(elegido.getNombrePaciente());
//Obtenemos su lista de vacunas para mostra en el selector
listaVacunas.removeAllItems();
for (String item: elegido.getListaIdVacunas())
listaVacunas.addItem(item);
listaVacunas.setSelectedIndex(-1);
jtNombre.setText(null);
jtFecha.setText(null);
}
}
}

private class AccionListaVac implements ItemListener {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == 1) { //Se ha elegido una vacuna, la buscamos
String id = (String) e.getItem();
Vacuna elegida = elegido.getVacuna(id);
//Mostramos sus datos
jtNombre.setText(elegida.getNombreVacuna());
jtFecha.setText(elegida.getFechaAplicacion());
}
}
}

private class AccionAgregar implements ActionListener {
//Registra un nueva vacuna en el paciente elegido actualmente
@Override
public void actionPerformed(ActionEvent e) {
String nombre = jtNombre.getText();
String fecha = jtFecha.getText();
if (nombre.isBlank())
alerta("Campo NOMBRE no puede estar vacío");
else if (fecha.isBlank())
alerta("Campo FECHA APLICACION no puede estar vacío");
else {
String idGenerado = elegido.agregarVacuna(fecha, nombre);
listaVacunas.addItem(idGenerado);
listaVacunas.setSelectedItem(idGenerado);
alerta("Nueva Vacuna registrada");
}

}
}

private class AccionModificar implements ActionListener {
//Modifica la vacuna actual
@Override
public void actionPerformed(ActionEvent e) {
int respuesta = JOptionPane.showConfirmDialog(null, "¿Modificar la Vacuna seleccionada?",
"Modificar Vacuna", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION) {
String id = (String)listaVacunas.getSelectedItem();
String nombre = jtNombre.getText();
String fecha = jtFecha.getText();
if (nombre.isBlank())
alerta("Campo NOMBRE no puede estar vacío");
else if (fecha.isBlank())
alerta("Campo FECHA APLICACION no puede estar vacío");
else {
elegido.modificarVacuna(new Vacuna(id, fecha, nombre));
alerta("Cambios guardados");
}
}
}
}

private class AccionBorrar implements ActionListener {
//Elimina la vacuna actual
@Override
public void actionPerformed(ActionEvent e) {
String eliminar = (String)listaVacunas.getSelectedItem();
int respuesta = JOptionPane.showConfirmDialog(null, "¿Eliminar la Vacuna seleccionada?",
"Eliminar Vacuna", JOptionPane.YES_NO_OPTION);
if (respuesta == JOptionPane.YES_OPTION) {
elegido.eliminarVacuna(eliminar);
listaVacunas.removeItem(eliminar);
listaVacunas.setSelectedIndex(-1);
jtNombre.setText(null);
jtFecha.setText(null);
}
}
}

private class AccionReset implements ActionListener {
//Borra los valores de los campos del formulario
@Override
public void actionPerformed(ActionEvent e) {
resetFormulario();
}
}

}

Teniendo esta interfaz creada, solo hay que ir a la clase principal para hacer un pequeño cambio.
Ahí teníamos 4 métodos que se encargan de mostrar un panel u otro según elijamos en el menú superior de la interfaz.
En dos de esos métodos ya tenemos puesto el código para que muestren pacientes y vacunas cuando corresponda.
Pero además, para que tras cada cambio nos encontremos con los formularios limpios y los datos de los JComboBox actualizados, he puesto que previamente se invoquen los métodos resetFormulario() de ambas pantallas.
Este método lo pusimos como private en PantallaPaciente, habría que cambiarlo a public

Citar
   private void gestionarPacientes() {
      pantallaPaciente.resetFormulario();
      paneles.show(getContentPane(), "Pacientes");
   }
   private void gestionarVacunas() {
      pantallaVacuna.resetFormulario();
      paneles.show(getContentPane(), "Vacunas");
   }
   private void gestionarCitas() {
      JOptionPane.showMessageDialog(null, "Pantalla aún no construida");
   }
   private void gestionarExpedientes() {
      JOptionPane.showMessageDialog(null, "Pantalla aún no construida");
   }


Con esto, ya deberías poder continuar tú con la gestión de citas y expedientes.

Se que no es fácil asimilar una gran cantidad de código que ha escrito otra persona, así que revisa bien lo que se ha escrito hasta ahora y pregunta lo que necesites, sea lo que sea.

Adjunto un nuevo .zip con los últimos cambios hechos en el código.
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

jonij

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 8
    • Ver Perfil
Re: Relación entre Clases
« Respuesta #7 en: 04 de Noviembre 2023, 04:28 »
Hola Kabuto, muchas gracias, tu guía me ha servido de mucha ayuda. En este momento, estoy intentando hacer las clases Cita y PantallaCita para poder agregar citas a un paciente.

Sin embargo, pienso que para Expediente sería diferente. Quiero que un paciente tenga un solo expediente, y, a su vez, un expediente solo pueda estar relacionado con un solo paciente.

Además, necesito tomar los datos del paciente y las vacunas que se le han aplicado; esta información debe estar incluida en el expediente del paciente. ¿Que tan factible es hacer esto?

También me gustaría que la información del expediente de un paciente se pueda mostrar en un JTextArea.

Además, estaba considerando crear un ArrayList de tipo String en la clase Expediente que contenga los medicamentos del paciente.

La clase Expediente:

package modelo;

import java.util.ArrayList;

public class Expediente {

    private String idNumIdentificacioExpediente;
    private String diagnostico;
    private ArrayList<String> medicamentos;

    public Expediente() {
    }

    public Expediente(String idNumIdentificacioExpediente, String diagnostico, ArrayList<String> medicamentos) {
        this.idNumIdentificacioExpediente = idNumIdentificacioExpediente;
        this.diagnostico = diagnostico;
        this.medicamentos = medicamentos;
    }

    public String getIdNumIdentificacioExpediente() {
        return idNumIdentificacioExpediente;
    }

    public String getDiagnostico() {
        return diagnostico;
    }



    public void setIdNumIdentificacioExpediente(String idNumIdentificacioExpediente) {
        this.idNumIdentificacioExpediente = idNumIdentificacioExpediente;
    }

    public void setDiagnostico(String diagnostico) {
        this.diagnostico = diagnostico;
    }


}


Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: Relación entre Clases
« Respuesta #8 en: 05 de Noviembre 2023, 10:50 »
Citar
Quiero que un paciente tenga un solo expediente, y, a su vez, un expediente solo pueda estar relacionado con un solo paciente.

Además, necesito tomar los datos del paciente y las vacunas que se le han aplicado; esta información debe estar incluida en el expediente del paciente. ¿Que tan factible es hacer esto?

Eso es totalmente factible. La cuestión es decidir cómo quieres establecer esa relación.

Puedes hacer que Expediente tenga como atributo el objeto Paciente con el que se relaciona:
Citar
public class Expediente {

    private String idNumIdentificacioExpediente;
    private String diagnostico;
    private Paciente paciente;
    private ArrayList<String> medicamentos;


Pero también puedes "dar la vuelta a la tortilla" y hacer que sea Paciente quien tenga como atributo un objeto Expediente.
Citar
public class Paciente {

    private String numIdentificacionPaciente;
    private String nombrePaciente;
    private int edadPaciente;
    private String sexoPaciente;
    private double alturaPaciente;
    private double pesoPaciente;
    private String fechaNacPaciente;
    //Vacunas
    private ArrayList<Vacuna> vacunas;
    //Expediente
    private Expediente expediente;

Aunque luego Expediente tenga su propia "pantalla" ajena a la "pantalla" de Paciente, puedes hacer que expediente sea parte de paciente.
Así además no tendrías que crear una colección donde almacenar todos los expedientes, ya que estos quedarían guardados en el HashMap de los pacientes.

Sí tendrías que ampliar los métodos de la clase GestorPacientes, para que ahora pudiera también gestionar los expedientes que poseen los pacientes.

Resumiendo, hay dos posibilidades.

-Hacer que Expediente tenga un atributo Paciente.
Necesitarás crear además una colección para almacenar los expedientes y una clase que los "gestione"(crear, modificar, consultar...)

- Hacer que Expediente sea un atributo de Paciente.
No necesitarás crear una colección de expedientes porque estarían almacenados en el HashMap de Pacientes. Pero sí que habrá que modificar la clase GestorPacientes para que pueda gestionar el expediente de cada paciente.


Ambas posibilidades son válidas. No hay una mejor que otra.
Elige la que más te guste o bien tirando una moneda al aire y que decida el azar  ;D
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

jonij

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 8
    • Ver Perfil
Re: Relación entre Clases
« Respuesta #9 en: 05 de Noviembre 2023, 16:55 »
Ok, en este caso me iría por la segunda opción.

jonij

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 8
    • Ver Perfil
Re: Relación entre Clases
« Respuesta #10 en: 06 de Noviembre 2023, 07:16 »
Porque cuando quisiese borrar un paciente también que se borrase su expediente de manera automática.

jonij

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 8
    • Ver Perfil
Re: Relación entre Clases
« Respuesta #11 en: 08 de Noviembre 2023, 20:53 »
Hola buen día es necesario que se modifique el constructor de Paciente para incluir el expediente?


Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 988
    • Ver Perfil
Re: Relación entre Clases
« Respuesta #12 en: 08 de Noviembre 2023, 22:25 »
Hola buen día es necesario que se modifique el constructor de Paciente para incluir el expediente?

Como el expediente se va a crear de forma posterior a la creación del paciente, lo único que habría que poner en el constructor es una inicialización para evitar que el atributo expediente quede con valor null.

Es decir, no se va a recibir ningún expediente por el constructor. Pero sí se va a inicializar, pues siempre es mejor un expediente "vacío" que no un valor null.

Citar
public class Paciente {

    private String numIdentificacionPaciente;
    private String nombrePaciente;
    private int edadPaciente;
    private String sexoPaciente;
    private double alturaPaciente;
    private double pesoPaciente;
    private String fechaNacPaciente;
    //Vacunas
    private ArrayList<Vacuna> vacunas;
    private Expediente expediente;

    public Paciente() {
    }

    public Paciente(String numIdentificacionPaciente, String nombrePaciente, int edadPaciente, String sexoPaciente, double alturaPaciente, double pesoPaciente, String fechaNacPaciente) {
        this.numIdentificacionPaciente = numIdentificacionPaciente;
        this.nombrePaciente = nombrePaciente;
        this.edadPaciente = edadPaciente;
        this.sexoPaciente = sexoPaciente;
        this.alturaPaciente = alturaPaciente;
        this.pesoPaciente = pesoPaciente;
        this.fechaNacPaciente = fechaNacPaciente;
        vacunas = new ArrayList<Vacuna>();
        expediente = new Expediente();
    }

Posterior a la creación del paciente, se le podrá hacer llegar un expediente con datos mediante un setter y recuperarlo con un getter
Código: [Seleccionar]
public Expediente getExpediente() {
return expediente;
}

public void setExpediente(Expediente expediente) {
this.expediente = expediente;
}
« Última modificación: 08 de Noviembre 2023, 22:27 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

jonij

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 8
    • Ver Perfil
Re: Relación entre Clases
« Respuesta #13 en: 10 de Noviembre 2023, 05:47 »
Ok, muchas gracias Kabuto.

 

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".