jairogarcíarincón
03/12/2018
Contenidos
- Introducción a JavaFX y Prerrequisitos
- LibretaDirecciones: Creación del proyecto y configuración
- LibretaDirecciones: Modelo y Lista de personas
- LibretaDirecciones: Interacción con el usuario
- LibretaDirecciones: Hojas de estilo CSS
- LibretaDirecciones: Persistencia de datos con XML
- LibretaDirecciones: Gráficos e Informes
- LibretaDirecciones: Despliegue
- LibretaDirecciones: Persistencia con base de datos con MySQL (local)
- LibretaDirecciones: Persistencia con base de datos con MySQL (remota)
Ya que nuestra LibretaDirecciones incluye las fechas de nacimiento de cada persona, vamos a generar un informe que me permita mostrar en forma de gráfico de barras la cantidad de personas que nacen en cada mes del año.
Para ello, crearemos una nueva vista llamada VistaEstadisticas.fxml dentro del paquete view y, desde Scene Builder, le aplicaremos las siguientes características:
- En la sección layout(derecha) del AnchorPane, establece Pref Width y Pref Height a 620x450.
- Desde la sección Charts (izquierda) añade un BarChart dentro del AnchorPane.
- Haz clic derecho sobre el BarChart y selecciona Fit to parent.
- Guarda el archivo.
Para controlar la vista, crea una nueva clase Java llamada VistaEstadisticasController dentro del paquete view con el siguiente código:
public class VistaEstadisticasController {
@FXML
private BarChart<String, Integer> graficoBarras;
@FXML
private CategoryAxis ejeX;
@FXML
private NumberAxis ejeY;
private ObservableList<String> nombreMeses = FXCollections.observableArrayList();
//Se invoca justo después de que se ha cargado el archivo FXML
@FXML
private void initialize() {
//Array de nombre de meses
String[] meses = {"Ene","Feb","Mar","Abr","May","Jun","Jul","Ago","Sep","Oct","Nov","Dic"};
//Los convierto a lista obervable
nombreMeses.addAll(Arrays.asList(meses));
//Asigno los nombres de meses a categorías
ejeX.setCategories(nombreMeses);
//Etiquetas de los ejes
ejeX.setLabel("Mes de nacimiento");
ejeY.setLabel("Número de personas");
}
//Set mes de cada persona para el eje Y
public void setDatosPersona(List<Persona> personas) {
//Array con cantidad de personas por mes de nacimiento
int[] numMes = new int[12];
for (Persona p : personas) {
int mes = p.getFechaDeNacimiento().getMonthValue() - 1;
numMes[mes]++;
}
//Genero la serie
XYChart.Series<String, Integer> series = new XYChart.Series<>();
series.setName("Mes de nacimiento");
for (int i = 0; i < numMes.length; i++) {
series.getData().add(new XYChart.Data<>(nombreMeses.get(i), numMes[i]));
}
//Añado la serie al gráfico
graficoBarras.getData().add(series);
}
}
Como vemos, el controlador necesitará acceso a dos elementos de nuestro archivo FXML:
- graficoBarras, que tiene los tipos String (meses en eje X) e Integer (número de personas en ese mes en el eje Y)
- ejeX: Lo usaremos para añadir las nombres de los meses
El método initialize() rellena el eje X con la lista de todos los meses. El método setDatosPersona(...)será llamado por la clase LibretaDirecciones para establecer los datos de personas, recorriendo todas ellas y contando los nacimientos por mes, que luego añadirá a un nuevo XYChart.Data (una barra en el gráfico) para cada mes a la serie de datos. Para finalizar, añado la serie al gráfico.
Como en anteriores ocasiones, abre VistaEstadisticas.fxml en Scene Builder y realiza las siguientes acciones:
En Controller (izquierda) selecciona VistaEstadisticasController como Controller class.
En Hierarchy (izquierda), selecciona el BarChart y, en Properties(derecha) escribe fecha de nacimientocomo Title.
En Hierarchy (izquierda), selecciona el BarChart y, en Code (derecha) asigna graficoBarras como fx:id.
En Hierarchy (izquierda), selecciona CategoryAxis dentro de BarChart y, en Code (derecha) asigna ejecomo fx:id.
Para el gráfico de estadísticas usaremos el mismo mecanismo que utilizamos para el diálogo de edición de personas, una ventana de diálogo emergente.
Añade el siguiente método a tu clase LibretaDirecciones (declarando primero la variable vistaEstadisticas de tipo AnchorPane):
public void crearGrafico() {
//Cargo la vista estadísticas
FXMLLoader loader = new FXMLLoader();
URL location = LibretaDirecciones.class.getResource("/view/VistaEstadisticas.fxml");
loader.setLocation(location);
try {
vistaEstadisticas = loader.load();
} catch (IOException ex) {
Logger.getLogger(LibretaDirecciones.class.getName()).log(Level.SEVERE, null, ex);
}
//Inicializo un nuevo escenario y asigno el principal
Stage escenarioEstadisticas = new Stage();
escenarioEstadisticas.setTitle("Estadísticas");
escenarioEstadisticas.initModality(Modality.WINDOW_MODAL);
escenarioEstadisticas.initOwner(escenarioPrincipal);
//Cargo la escena que contiene ese layout de estadisticas
Scene escena = new Scene(vistaEstadisticas);
escenarioEstadisticas.setScene(escena);
//Asigno el controlador
VistaEstadisticasController controller = loader.getController();
controller.setDatosPersona(datosPersona);
//Muestro el escenario
escenarioEstadisticas.show();
}
En VistaPrincipal.fxml, añade un nuevo menú llamado Estadísticas con un MenuItem llamado Gráfico.
En VistaPrincipalController, añade el siguiente método para controlar esa acción de menú:
//Gráfico
@FXML
private void grafico() {
libretaDirecciones.crearGrafico();
}
Por último, en VistaPrincipal.fxml, selecciona el MenuItem Gráficode Estadísticas y, en Code (derecha), selecciona grafico para el campo On Action.
Más información sobre gráficos con JavaFX AQUÍ.
Para generar un informe en PDF de nuestra libreta de direcciones, haremos uso de librería externa Apache PDFBox.
Para ello, debemos acceder a la sección Downloads de la página y descargarnos el fichero pdfbox-app-2.0.13.jar o la versión más reciente que encontremos.
Una vez descargada la librería, podemos añadirla a nuestro proyecto NetBeans en las Properties de nuestro proyecto (botón derecho), accediendo a la sección Libraries y añadiendo la ruta de nuestro archivo jar mediante el botón Add JAR/Folder..
De este modo, ya podremos crear un nuevo método en la clase principal LibretaDirecciones que genere un PDF básico con el contenido de nuestra libreta.
public void crearPDF() throws IOException{
//Creo un nuevo documento, una página y la añado
PDDocument documento = new PDDocument();
PDPage pagina = new PDPage();
documento.addPage(pagina);
documento.getPage(0);
//Inicio un nuevo stream de contenido
PDPageContentStream contentStream = new PDPageContentStream(documento, pagina);
//Establezco la posición Y de la primera líena y el tipo de fuente
int linea = 700;
contentStream.setFont(PDType1Font.TIMES_ROMAN, 12);
//Recorro la lista de personas
List<Persona> personas = datosPersona;
for (Persona p : personas) {
//Inicio un nuevo texto y escribo los datos
contentStream.beginText();
contentStream.newLineAtOffset(25, linea);
contentStream.showText(p.getNombre()+" ");
contentStream.showText(p.getApellidos()+" ");
contentStream.showText(p.getDireccion()+" ");
contentStream.endText();
//Cambio de línea
linea -= 25;
}
//Cierro el content stream
contentStream.close();
//INicio el file chooser
FileChooser fileChooser = new FileChooser();
//Filtro para la extensión
FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter(
"PDF files (*.pdf)", "*.pdf");
fileChooser.getExtensionFilters().add(extFilter);
//Muestro el diálogo de guardar
File archivo = fileChooser.showSaveDialog(getPrimaryStage());
if (archivo != null) {
//Me aseguro de que tiene la extensión correcta y si no la cambio
String extension = "";
if (!archivo.getPath().endsWith(extension)){
extension = ".pdf";
}
//Escribo en el archivo y lo cierro
archivo = new File(archivo.getPath() + extension);
documento.save(archivo);
documento.close();
}
//Abro el archivo en el visor de PDF del sistema
if (Desktop.isDesktopSupported()) {
try {
Desktop.getDesktop().open(archivo);
}
catch (IOException ex) {
}
}
}
Solo faltarían dos cosas: añadir un método para la acción del menú que generará un PDF en VistaPrincipalController:
//PDF
@FXML
private void pdf() throws IOException {
libretaDirecciones.crearPDF();
}
Y añadir un MenuItem llamado PDF dentro del Menu Estadísticas al que le asignaremos como On Action el método pdf.
El PDF aquí generado es bastante simple y muestra las opciones básicas. Puedes seguir ESTE TUTORIAL para generar PDFs más completos.
Publicado el 30 de Enero de 2025
xmlinterfacesjavafx