Mostrar Mensajes

Esta sección te permite ver todos los posts escritos por este usuario. Ten en cuenta que sólo puedes ver los posts escritos en zonas a las que tienes acceso en este momento.


Mensajes - Kabuto

Páginas: [1] 2 3 4 5 6 ... 50
1
Gracias por compartirlo.

Otra solución sería usando un bucle while que se repita hasta que el usuario indique que quiere salir.
Los bucles while son más cómodos en casos en los que NO sabemos exactamente cuántas veces se va a repetir algo. Los bucles for son más apropiados para los casos en que sabemos cuántas veces se ha de repetir su código.
Así no hay necesidad de "romper"(break) el bucle

Código: [Seleccionar]
print("bienvenido a la calculadora de aprendeprogramar")
print("las operaciones son suma,resta,division,multiplicacion\n")
num1 = 0
num2 = 0
operacion = "nada"
resultado = 0
salir = "no"

while salir != "si":
    num1 = int(input("Ingrese 1er numero: "))
    num2 = int(input("Ingrese 2do numero: "))
    operacion = input("Ingrese operacion: ")
    if operacion == "suma":
        resultado = num1 + num2
        print(f"La suma es: {resultado}")
    elif operacion == "resta":
        resultado = abs(num1 - num2)
        print(f"La resta es: {resultado}")
    elif operacion == "multiplicacion":
        resultado = abs(num1 * num2)
        print(f"La multiplicacion es: {resultado}")
    elif operacion == "division":
        resultado = abs(num1 / num2)
        print(f"La division es: {resultado}")
    else:
        print("Operacion no reconocida...")
    salir = input("\nDesear salir?(si/no): ").lower()

print("\n\t\tFIN DE PROGRAMA")

2
Hola.
La API de Java no incluye librerías para acceder a tipos de datos de Microsoft, así que hay que usar librerías de terceros.

Para esto, la más conocida(al menos la que yo conozco) es Apache Poi.
Desde su web puedes obtener la última versión, documentación sobre su API, etc....

Sin embargo, para usar su última versión hay que construir la librería usando Gradle y es más complicado y hasta yo me pierdo con eso.

Tengo unos archivos .jar de esta librería listos para ser usados. Son una versión antigua, pero bueno, sirven igualmente.
Se pueden descargar desde este enlace Drive

Para usarlos en tu proyecto Java, lo que tienes que hacer es copiarlos a una carpeta dentro de tu proyecto. Puedes llamar a esa carpeta como quieras, lo habitual es llamarla "lib", para indicar que ahí contenemos unas librerías.
Luego, para que tu proyecto pueda usarlas, tienes que "construir una ruta"(build path) hacia ellas.

La forma de hacer esto puede variar según el IDE que estés usando. Por ejemplo en Eclipse, el que yo uso, la opción es "Build Path" > "Add External Archives"



Y entonces se abre un explorador de archivos donde seleccionar los .jar de Apache Poi.

Una vez hecho esto, ya podemos hacer import de las clases que necesitemos para interactuar con el Excel.

Un archivo Excel es bastante complejo, a parte de que los hay de distintos tipos(si son Excel antiguos de antes de mediados del año 2000 hay que usar la clase HSSF, si no hay que usar XSSF para los posteriores más actuales), un archivo Excel es como un libro que se compone de una o más hojas.
Y cada hoja se compone de filas.
Y cada fila se compone de celdas.

Así que para trabajar con el Excel, hay que crear objetos que representen cada uno de esos elementos.

Dejo un ejemplo muy sencillo para leer un Excel y volcar los datos en pantalla.

Fíjate que la lógica es muy simple.
Creamos un libro a partir del fichero y de este libro obtenemos un "iterador" para recorrer las hojas que pueda tener.
Por cada hoja, obtenemos otro "iterador" para recorrer las filas que pueda tener.
Y por cada fila, otro "iterador" para recorrer las celdas.

Cada "iterador" lo recorremos mediante un bucle while, así que tenemos tres bucles anidados.

Código: [Seleccionar]
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Iterator;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class LectorExcel {

public static void main(String[] args) {

File fichero = new File("e:/clientes.xlsx");
try {
//Leemos los bytes del fichero Excel y creamos un "libro de trabajo"
FileInputStream datosExcel = new FileInputStream(fichero);
XSSFWorkbook libroDeTrabajo = new XSSFWorkbook(datosExcel);

/*
* El "libro de trabajo" Excel está compuesto
* de una o más hojas(sheets).
* Creamos un Iterador para recorrerlas
*/
Iterator<Sheet> hojasLibro = libroDeTrabajo.sheetIterator();
while(hojasLibro.hasNext()) {
XSSFSheet hojaExcel = (XSSFSheet) hojasLibro.next();
System.out.println("\n\n\t\tNUEVA HOJA EXCEL. FILAS: " + hojaExcel.getPhysicalNumberOfRows());
System.out.println("\t\t----- ---- ------ ----------\n");
/*
* Cada hoja se compone de filas y cada fila se compone de celdas
* Habrá que iterar cada fila, y por cada fila iterar sus celdas
*/
Iterator<Row> filasExcel = hojaExcel.iterator();
while(filasExcel.hasNext()) {
Row fila = filasExcel.next();
//Tenemos una fila, vamos a por sus celdas
Iterator<Cell> celdasExcel = fila.cellIterator();
while(celdasExcel.hasNext()) {
Cell celda = celdasExcel.next();
/*
* Vamos a mostrar los datos de cada celda de esta fila.
* Pero antes de mostrar, tenemos que preguntar de qué tipo
* de dato se trata, pues puede ser numérico, cadena, fórmula, boolean...
* Y cada tipo de dato exige un método distinto para ser mostrado.
*
* En este ejemplo solo tendremos numéricos y cadenas.
*/
switch(celda.getCellType()) {
case Cell.CELL_TYPE_STRING:
System.out.print(celda.getStringCellValue() + "\t\t");
break;
case Cell.CELL_TYPE_NUMERIC:
System.out.print(celda.getNumericCellValue() + "\t\t");
break;
}
}
System.out.println();//Final de esta fila
}
}
libroDeTrabajo.close();
System.out.println("\n\n\t\tFIN DE PROGRAMA");

} catch (FileNotFoundException e) {
System.err.println("Fichero Excel no encontrado");
} catch (IOException e) {
System.err.println("Error al acceder archivo Excel");
}
}
}


Esto es solo un ejemplo básico. La librería Apache Poi es muy extensa y permite hacer muchas cosas.
Ahora que ya sabes lo que necesitas, sigue buscando tú mismo más ejemplos de uso para leer y modificar datos, y que sean más actualizados que el que yo he puesto.

Por ejemplo, el método que uso en el switch para comprobar el tipo de dato que contiene la celda, está obsoleto. Funciona, pero tiene que haber otro método o manera de hacerlo más actualizada.

Un saludo.

3
Comunidad / Re: ayuda porfavor!
« en: 27 de Abril 2024, 23:03 »
Hola.
Comienza tú un código y te vamos ayudando a completar y resolver dudas.

Empieza escribiendo la clases Empleado y Nómina, olvídate del resto del enunciado hasta no tener estas clases.
Es decir, de momento solo interésate por esto:
Citar
De los empleados interesa conocer su NIF, nombre, apellidos, puesto, salario mensual y datos de la nómina.

Para los datos de la nómina tendremos, salario base, plus de convenio, complementos y descuento de IRPF que será en torno al 10-18% del salario base (nótese la simplificación en relación a la realidad, este valor se calculará con un aleatorio en ese rango).

La clase empleado tendrá un método que calculará el salario neto que percibirá mensualmente (salarioMensual), que será la suma del salario base, plus, complementos y descontando el IRPF.

Comparte aquí lo que vayas escribiendo y te vamos ayudando.

4
Tras casi 4 años abandonado es un poco difícil retomar un código tan grande, pero a raíz de lo que me consultaste en privado la verdad es que me ha despertado el gusanillo.
Luego con tiempo me lo miro bien a ver si veo factible retomarlo.

5
Aprender a programar desde cero / Re: Ayuda con Java
« en: 13 de Abril 2024, 18:15 »
Esta web ofrece un curso gratuito para aprender Java

Puedes consultar a partir del capítulo 23 y siguientes

6
Sería interesante, pero como dices, probablemente no puedas colgar un zip en tu mensaje por el peso de las imágenes que estés usando.

Quizás puedas subirlo a Google Drive o similar y compartir el enlace.


Un saludo.

7
Hola, me da un error de compilación en public class GameBoard en el metodo

En la línea if (o instanceof Ball ball) marca el error --------  ')' expected

Prueba a quitar el segundo ball, en minúscula. Ahí solo debería interesar el nombre de la clase, que es Ball (mayúscula)

Citar
if (o instanceof Ball ball)

8
Comunidad / Re: Feliz Navidad y Próspero Año Nuevo para todos
« en: 10 de Diciembre 2023, 11:14 »
Me alegra poder seguir comiendo el turrón navideño aquí con vosotros.

Feliz Navidad a todo el mundo  ;D

9
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;
}

10
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

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

12
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

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

14
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

15
Yo soy más de Java y no puedo darte un código C# concreto para solucionarlo.
Pero la lógica que yo intentaría seguir (independientemente del lenguaje) sería crear un array con esos textbox.

Entonces, aquí, en lugar de recorrer el array salida y escribir los datos en consola
Código: [Seleccionar]
foreach (var c in salida)
{
        Console.WriteLine(c);
}

Lo que haría será pasar esos datos a los textbox del array.

Podría ser algo como esto, aunque puede que haya algún error de sintaxis.
Ya te digo que en C# estoy muy verde.... :P

Código: [Seleccionar]
//Construcción de una lista de boxes
List<TextBox> listaDeBoxes = new List<TextBox>();
listaDeBoxes.Add(textBox_I);
listaDeBoxes.Add(textBox_O);
listaDeBoxes.Add(textBox_L);
listaDeBoxes.Add(textBox_B);
listaDeBoxes.Add(textBox_V);
listaDeBoxes.Add(textBox_F);
listaDeBoxes.Add(textBox_H);
listaDeBoxes.Add(textBox_R);
//Indice para recorrer cada elemento de la lista
int i = 0;

foreach (var c in salida)
{
        listaDeBoxes[i].Text = c; //Asignamos valor al textBox
        i++; //Incrementamos indice para pasar al siguiente textBox
}

16
A ver si este ejemplo te ayuda.
No se como construirás tú las interfaces Swing, supongo que con el GUI Builder de NetBeans, porque es lo que enseñan en todas partes.

Yo las hago escribiendo código, pero bueno, al fin y al cabo la lógica es la misma.
La interfaz que yo proponía era algo así:


Tres paneles, cada uno con sus botones y campos.
Cada panel se puede escribir como una clase independiente de las otras, así que cada botón puede acceder directamente a los campos que necesita para coger los datos y mostrar resultados.
En el ActionListener que escribimos para cada botón, le decimos con que campos ha de interactuar.
En mi caso, puesto que los escribo como clases independientes, es más fácil y queda más ordenado.
Si se hace con el builder y escrito todo como un único form, puede quedar más caótico al estar todos los JTextField declarados en una misma clase.
Pero bueno, mientras a cada uno se le de un nombre adecuado, luego en los ActionListener tan solo hay que llamar a los que corresponda según la figura.

En mi caso, tengo una clase PanelTriangulo
Código: [Seleccionar]
public class PanelTriangulo extends JPanel {

private JTextField campoAltura;
private JTextField campoBase;
private JTextField campoResultado;
private JButton btCalcular;

public PanelTriangulo() {
campoBase = new JTextField(8);
campoAltura = new JTextField(8);
campoResultado = new JTextField(8);
campoResultado.setEditable(false);
btCalcular = new JButton("Calcular");
btCalcular.addActionListener(new AccionCalcular());

setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
JLabel lbImagen = new JLabel(new ImageIcon(this.getClass().getClassLoader().getResource("areasFigurasSwing/triangulo.jpg")));
lbImagen.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
add(lbImagen);
add(new PanelCampo("Valor de Base: ", campoBase));
add(new PanelCampo("Valor de Altura: ", campoAltura));
JPanel pnBoton = new JPanel();
pnBoton.add(btCalcular);
add(pnBoton);
add(new PanelCampo("Area: ", campoResultado));

setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(15, 15, 15, 15),
BorderFactory.createTitledBorder("Area del Triangulo")));
}

private class AccionCalcular implements ActionListener {

@Override
public void actionPerformed(ActionEvent e) {
try {
double base, altura;
if (campoBase.getText().isBlank())
JOptionPane.showMessageDialog(null, "Introduzca valor de la Base");
else if (campoAltura.getText().isBlank())
JOptionPane.showMessageDialog(null, "Introduzca valor de la Altura");
else {
base = Double.parseDouble(campoBase.getText());
altura = Double.parseDouble(campoAltura.getText());
campoResultado.setText(String.format("%.2f", (base * altura) / 2));
}
}
catch(Exception ex) {
JOptionPane.showMessageDialog(null, "Introduzca valores numéricos");
}
}
}
}
Otra clase PanelCirculo
Código: [Seleccionar]
public class PanelCirculo extends JPanel {

private JTextField campoRadio;
private JTextField campoResultado;
private JButton btCalcular;

public PanelCirculo() {
campoRadio = new JTextField(8);
campoResultado = new JTextField(8);
campoResultado.setEditable(false);
btCalcular = new JButton("Calcular");
btCalcular.addActionListener(new AccionCalcular());

setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
JLabel lbImagen = new JLabel(new ImageIcon(this.getClass().getClassLoader().getResource("areasFigurasSwing/circulo.jpg")));
lbImagen.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
add(lbImagen);
add(new PanelCampo("Valor de Radio: ", campoRadio));
JPanel pnBoton = new JPanel();
pnBoton.add(btCalcular);
add(pnBoton);
add(new PanelCampo("Area: ", campoResultado));

setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(15, 15, 15, 15),
BorderFactory.createTitledBorder("Area del Círculo")));
}

private class AccionCalcular implements ActionListener {

@Override
public void actionPerformed(ActionEvent e) {
try {
double radio;
if (campoRadio.getText().isBlank())
JOptionPane.showMessageDialog(null, "Introduzca valor del Radio");
else {
radio = Double.parseDouble(campoRadio.getText());
campoResultado.setText(String.format("%.2f", Math.PI * Math.pow(radio, 2)));
}
}
catch(Exception ex) {
JOptionPane.showMessageDialog(null, "Introduzca valores numéricos");
}
}
}
}

Y la clase PanelCuadrado
Código: [Seleccionar]
public class PanelCuadrado extends JPanel {

private JTextField campoLado;
private JTextField campoResultado;
private JButton btCalcular;

public PanelCuadrado() {
campoLado = new JTextField(8);
campoResultado = new JTextField(8);
campoResultado.setEditable(false);
btCalcular = new JButton("Calcular");
btCalcular.addActionListener(new AccionCalcular());

setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
JLabel lbImagen = new JLabel(new ImageIcon(this.getClass().getClassLoader().getResource("areasFigurasSwing/cuadrado.jpg")));
lbImagen.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
add(lbImagen);
add(new PanelCampo("Valor de Lado: ", campoLado));
JPanel pnBoton = new JPanel();
pnBoton.add(btCalcular);
add(pnBoton);
add(new PanelCampo("Area: ", campoResultado));

setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(15, 15, 15, 15),
BorderFactory.createTitledBorder("Area del Cuadrado")));
}

private class AccionCalcular implements ActionListener {

@Override
public void actionPerformed(ActionEvent e) {
try {
double lado;
if (campoLado.getText().isBlank())
JOptionPane.showMessageDialog(null, "Introduzca valor del Lado");
else {
lado = Double.parseDouble(campoLado.getText());
campoResultado.setText(String.format("%.2f", lado * lado));
}
}
catch(Exception ex) {
JOptionPane.showMessageDialog(null, "Introduzca valores numéricos");
}

}
}
}

Todas ellas usan una pequeña clase llamada PanelCampo que simplemente construye un subpanel con un JTextfield y un texto para acompañarlo con un JLabel:
Código: [Seleccionar]
public class PanelCampo extends JPanel {

public PanelCampo(String texto, JTextField campo) {

setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10));
add(new JLabel(texto));
add(campo);
}
}

Estas tres clases, se muestran en un mismo JFrame apilándolas en horizontal
Código: [Seleccionar]
public class Main extends JFrame {

public Main() {

setLayout(new BoxLayout(getContentPane(), BoxLayout.X_AXIS));
add(new PanelCuadrado());
add(new PanelCirculo());
add(new PanelTriangulo());

setTitle("Calcular Areas");
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 Main();
}
});
}

}

Si no se quiere mostrar los tres paneles al mismo tiempo, se puede usar la clase JTabbedPane, con la cuál podemos crear paneles con "pestañas" para seleccionar la que queramos.
Solo hay que hacer un pequeño cambio en el constructor del JFrame:

Citar
public class Main extends JFrame {
   
   public Main() {
      
      JTabbedPane tabs = new JTabbedPane();
      tabs.addTab("Cuadrado", new PanelCuadrado());
      tabs.addTab("Círculo", new PanelCirculo());
      tabs.addTab("Triangulo", new PanelTriangulo());
      getContentPane().add(tabs);

      
      setTitle("Calcular Areas");
      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 Main();   
         }
      });
   }

}

Y de esta forma, la interfaz queda un poco más cuqui:


17
Hola.
De momento olvida la bola y céntrate en intentar representar la barra y su movimiento.

Quisiera hacer yo un intento, pero no se cuándo podré, no tengo tiempo ni para cag..., digo.., pensar... ::)

18
Hola.

Cada botón tendrá asociado su propio ActionListener, ¿no? Es decir, el código que le dice qué tiene que hacer dicho botón cuando sea pulsado.
Pues en ese código, a cada botón se le dirá que coja los datos de los TextField que le correspondan.

La interfaz, si no han dado indicaciones más específicas, se puede hacer mostrando tres JPanel en el JFrame, uno al lado del otro, donde cada JPanel corresponda a una de las tres figuras geométricas. Así todo está visible y no hay mayor complicación.

19
Hola.
La respuesta puede ser correcta, en cuanto parece que has captado la idea.
Cuando hablamos de clases y superclase, nos referimos a entidades e ideas más bien abstractas.
En cambio, al hablar de objetos, ya si nos referimos a entidades más concretas y únicas, creadas a partir del concepto que describen las clases a las que pertenecen dichos objetos.

A modo de ejercicio extra, ¿serías capaz de indicar uno o dos atributos para cada una de esas clases?

Teniendo en cuenta que la superclase Avión tendría atributos que serían comunes a todas las clases hijas (por ejemplo "altitud máxima de vuelo")

En cambio, las clases hijas, además de esos atributos comunes que heredan de la superclase, tendrían otros atributos que serían únicos para cada una de ellas.
Por ejemplo, AvionPasajeros podría tener un atributo que fuera "número de asientos" (para los pasajeros).

Pero ese atributo no tendría sentido para AvionCarga y desde luego tampoco para AvionCombate

A ver si se te ocurren un par de atributos comunes a todos los Aviones y otros que sean exclusivos de cada subclase.

Un saludo.

20
Sí.
El cálculo que se hace en ese código es más completo, hermoso y preciso.

Pero a la hora de la verdad, cuándo toca pintar la bola, se hace un redondeo y se castea a valores enteros:

Citar
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            Ball ball = model.getBall();
            Point2D point = ball.getPosition();
            int x = (int) Math.round(point.getX());
            int y = (int) Math.round(point.getY());

Es decir, que si los cálculos dicen que la bola ha de avanzar 2,35 pixeles, pues avanzará 2 píxeles.
Y si dicen que ha de avanzar 2,84 píxeles, pues avanzará 3 píxeles.

Y es porque los píxeles son celdas físicas de una pantalla que, o están pintados de un color, o lo están de otro.
No puede estar 1/3 pixel pintado de blanco y los otros 2/3 pintados de azul, por ejemplo.

Es como si al caminar nosotros, solo pudiéramos avanzar metros completos, nunca medio metro, ni 1 metro y 750 cm...


En cualquier caso, con ese código ya no hay que hacer la "chapuza" que hice yo, de mantener constante una de las desviaciones para que la diferencia de velocidad en cada rebote no fuera tan notable.

Es lo bueno de saber matemáticas.
Es muy interesante, pero hay cosas que no entiendo.

Por ejemplo, no se por qué para el eje x se usa la constante 540 y para el eje y en cambio es 360  ???

Citar

        public void calculateNewPosition() {
            double theta = Math.toRadians(angle);
            double xDifference = Math.cos(theta) * speed;
            double yDifference = Math.sin(theta) * speed;
            xPosition += xDifference;
            yPosition += yDifference;

            if (xPosition < radius) {
                angle = 540 - angle;
            }

            if (xPosition > drawingPanelDimension.width - radius) {
                angle = 540 - angle;
            }

            if (yPosition < radius) {
                angle = 360 - angle;
            }

            if (yPosition > drawingPanelDimension.height - radius) {
                angle = 360 - angle;
            }

Páginas: [1] 2 3 4 5 6 ... 50

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