jairogarcíarincón

LibretaDirecciones: Modelo y Lista de personas


4.32K



El modelo Persona

Necesitamos un modelo para almacenar toda la información relativa a los contactos de la libreta. Para ello, dentro del paquete model, crearemos una nueva clase Java llamada Persona.

El código para la clase Persona se detalla a continuación, y los aspectos más relevantes del mismo serían:

  • Con JavaFX es habitual usar Propiedades para todos los atributos de una clase usada como modelo, ya que nos van a permitir, entre otras cosas, mantener sincronizados la vista y los datos cuando los valores de las variables cambien. Más información sobre Properties and Binding.
  • LocalDate, el tipo que usamos para especificar la fecha de nacimiento. Más información sobre Standard Calendar.



package model;

import java.time.LocalDate;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class Persona {

private final StringProperty nombre;
private final StringProperty apellidos;
private final StringProperty direccion;
private final StringProperty ciudad;
private final IntegerProperty codigoPostal;
private final ObjectProperty fechaDeNacimiento;

public Persona() {
this(null, null);
}

public Persona(String nombre, String apellidos) {

this.nombre = new SimpleStringProperty(nombre);
this.apellidos = new SimpleStringProperty(apellidos);

this.direccion = new SimpleStringProperty("Mi dirección");
this.ciudad = new SimpleStringProperty("some city");
this.codigoPostal = new SimpleIntegerProperty(28440);
this.fechaDeNacimiento = new SimpleObjectProperty(LocalDate.of(1974, 6, 15));

}

public String getNombre() {
return nombre.get();
}

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

public StringProperty nombreProperty() {
return nombre;
}

public String getApellidos() {
return apellidos.get();
}

public void setApellidos(String apellidos) {
this.apellidos.set(apellidos);
}

public StringProperty apellidosProperty() {
return apellidos;
}

public String getDireccion() {
return direccion.get();
}

public void setDireccion(String direccion) {
this.direccion.set(direccion);
}

public StringProperty direccionProperty() {
return direccion;
}

public String getCiudad() {
return ciudad.get();
}

public void setCiudad(String ciudad) {
this.ciudad.set(ciudad);
}

public StringProperty ciudadProperty() {
return ciudad;
}

public int getCodigoPostal() {
return codigoPostal.get();
}

public void setCodigoPostal(int codigoPostal) {
this.codigoPostal.set(codigoPostal);
}

public IntegerProperty codigoPostalProperty() {
return codigoPostal;
}

public LocalDate getFechaDeNacimiento() {
return fechaDeNacimiento.get();
}

public void setFechaDeNacimiento(LocalDate fechaDeNacimiento) {
this.fechaDeNacimiento.set(fechaDeNacimiento);
}

public ObjectProperty fechaDeNacimientoProperty() {
return fechaDeNacimiento;
}

}


La lista de personas

El objetivo de nuestro proyecto era almacenar y gestionar una lista de personas, con lo que vamos a crear una lista de objetos de tipo Persona dentro de la clase LibretaDirecciones a la que luego podremos acceder desde cualquiera de los otros controladores.

Lista observable (ObservableList)

Para poder pasar y mantener sincronizados los datos de la lista de personas en las clases gráficas de JavaFX, utilizamos las denominadas clases de colección de JavaFX, de las cuales usaremos una ObservableList.

Se ha modificado el código de la clase principal LibretaDirecciones, de modo que ahora incluya nuestra variable ObservableList y un método de consulta (get) público. Además, hemos añadido un constructor para crear datos de ejemplo:



package controller;

import java.io.IOException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import model.Persona;

public class LibretaDirecciones extends Application {

private ObservableList datosPersona = FXCollections.observableArrayList();
private Stage escenarioPrincipal;
private BorderPane layoutPrincipal;
private AnchorPane vistaPersona;

//Datos de ejemplo
public LibretaDirecciones(){

datosPersona.add(new Persona("Jairo", "García Rincón"));
datosPersona.add(new Persona("Juan", "Pérez Martínez"));
datosPersona.add(new Persona("Andrea", "Chenier López"));
datosPersona.add(new Persona("Emilio", "González Pla"));
datosPersona.add(new Persona("Mónica", "de Santos Sánchez"));

}

//Método para devolver los datos como lista observable de personas
public ObservableList getDatosPersona() {
return datosPersona;
}

@Override
public void start(Stage escenarioPrincipal) {

//Debo hacerlo para que luego me funcione en l carga de escenas
this.escenarioPrincipal = escenarioPrincipal;

//Establezco el título
this.escenarioPrincipal.setTitle("Libreta de direcciones");

//Inicializo el layout principal
initLayoutPrincipal();

//Muestro la vista persona
muestraVistaPersona();
}

public void initLayoutPrincipal(){

//Cargo el layout principal a partir de la vista VistaPrincipal.fxml
FXMLLoader loader = new FXMLLoader();
URL location = LibretaDirecciones.class.getResource("../view/VistaPrincipal.fxml");
loader.setLocation(location);
try {
layoutPrincipal = loader.load();
} catch (IOException ex) {
Logger.getLogger(LibretaDirecciones.class.getName()).log(Level.SEVERE, null, ex);
}

//Cargo y muestro la escena que contiene ese layout principal
Scene escena = new Scene(layoutPrincipal);
escenarioPrincipal.setScene(escena);
escenarioPrincipal.show();

}

public void muestraVistaPersona(){

//Cargo la vista persona a partir de VistaPersona.fxml
FXMLLoader loader = new FXMLLoader();
URL location = LibretaDirecciones.class.getResource("../view/VistaPersona.fxml");
loader.setLocation(location);
try {
vistaPersona = loader.load();
} catch (IOException ex) {
Logger.getLogger(LibretaDirecciones.class.getName()).log(Level.SEVERE, null, ex);
}

//Añado la vista al centro del layoutPrincipal
layoutPrincipal.setCenter(vistaPersona);

}

//Invoco el método getPrimaryStage para que devuelva mi escenario pñrincipal
public Stage getPrimaryStage() {
return escenarioPrincipal;
}

//Método main
public static void main(String[] args) {
launch(args);
}

}


El controlador para la vista de personas

Por último, tenemos que añadir los datos a nuestra tabla de VistaPersona.fxml, y para ello crearemos un controlador mediante una clase Java llamada VistaPersonaController dentro del paquete view para evitar incompatibilidades entre versiones de Scene Builder.

El código de la clase VistaPersonaController se muestra a continuación, y en él hay que destacar ciertos detalles:

  • Los campos y métodos donde el archivo fxml necesita acceso deben ser anotados con @FXML. En realidad, sólo si son privados, pero es mejor tenerlos privados y marcarlos con la anotación.
  • El método initialize() es invocado automáticamente tras cargar el fxml. En ese momento, todos los atributos FXML deberían ya haber sido inicializados.
  • El método setCellValueFactory(...) que aplicamos sobre las columnas de la tabla se usa para determinar qué atributos de la clase Persona deben ser usados para cada columna particular. La flecha -> indica que estamos usando una característica de Java 8 denominada Lambdas.
  • Acuérdate siempre de importar javafx, NO AWT ó Swing.




package view;

import javafx.fxml.FXML;
import javafx.scene.control.TableView;
import model.Persona;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;

public class VistaPersonaController {

@FXML
private TableView tablaPersonas;
@FXML
private TableColumn nombreColumn;
@FXML
private TableColumn apellidosColumn;

@FXML
private Label nombreLabel;
@FXML
private Label apellidosLabel;
@FXML
private Label direccionLabel;
@FXML
private Label codigoPostalLabel;
@FXML
private Label ciudadLabel;
@FXML
private Label fechaDeNacimientoLabel;

// Referencia a la clase principal
private LibretaDirecciones libretaDirecciones;

//El constructor es llamado ANTES del método initialize
public VistaPersonaController() {
}

//Inicializa la clase controller y es llamado justo después de cargar el archivo FXML
@FXML
private void initialize() {

//Inicializo la tabla con las dos primera columnas
String nombre = "nombre";
String apellidos = "apellidos";
nombreColumn.setCellValueFactory(new PropertyValueFactory<>(nombre));
apellidosColumn.setCellValueFactory(new PropertyValueFactory<>(apellidos));
}

//Es llamado por la apliación principal para tener una referencia de vuelta de si mismo
public void setLibretaDirecciones(LibretaDirecciones libretaDirecciones) {

this.libretaDirecciones = libretaDirecciones;

//Añado la lista obervable a la tabla
tablaPersonas.setItems(libretaDirecciones.getDatosPersona());
}

}


La conexión de LibretaDirecciones con VistaPersonaController

Debemos invocar el método setLibretaDirecciones desde la clase LibretaDirecciones, de modo que podamos acceder al objeto LibretaDirecciones y, entre otras cosas, obtener la lista de Persona. Para ello, debemos modificar el método muestraVistaPersona() en LibretaDirecciones para que incluya dicho acceso:


public void muestraVistaPersona(){

//Cargo la vista persona a partir de VistaPersona.fxml
FXMLLoader loader = new FXMLLoader();
URL location = LibretaDirecciones.class.getResource("../view/VistaPersona.fxml");
loader.setLocation(location);
try {
vistaPersona = loader.load();
} catch (IOException ex) {
Logger.getLogger(LibretaDirecciones.class.getName()).log(Level.SEVERE, null, ex);
}

//Añado la vista al centro del layoutPrincipal
layoutPrincipal.setCenter(vistaPersona);

//Doy acceso al controlador VistaPersonaCOntroller a LibretaDirecciones
VistaPersonaController controller = loader.getController();
controller.setLibretaDirecciones(this);

}


Vincular la vista al controlador

Para finalizar, debemos indicar a VistaPersona.fxml mediante Scene Builder cuál es su controlador y asociar los diferentes elementos de la TableView y del GridPane con las variables de VistaPersonaController:

  • Selecciona el controlador en el desplegable Controller class de la sección Controller (lado izquierdo) de VistaPersona.fxml.
  • Selecciona TableView en la sección Hierarchy y, en la pestaña Code (lado derecho), selecciona como fx:id tablaPersonas.
  • Haz lo mismo para las columnas, seleccionando nombreColumn y apellidosColumn como sus fx:id, respectivamente.
  • Para cada etiqueta o Label de la segunda columna, selecciona el fx:id correspondiente.


Si hemos hecho todo correctamente, al lanzar la aplicación (recuerda ejecutar Clean and Build a tu proyecto antes) debemos encontrar una vista similar a la mostrada al inicio del presente capítulo.


Publicado el 30 de Enero de 2025

xmlinterfacesjavafx