openxava / documentación / Generación de informes - Lección 4: Trabajando con imágenes

Video

En este video veremos cómo enviar imágenes desde OpenXava como parámetro y data source a nuestro reporte.

¿Problemas con la lección? Pregunta en el foro

Código

Puedes descargar el proyecto de esta lección. También puedes copiar el código que se usa en el video por aquí:

En el archivo PrintProductAction.java:
public class PrintProductAction extends JasperReportBaseAction {

	private Product product;
	
	@Override
	protected JRDataSource getDataSource() throws Exception {
		return new JRBeanCollectionDataSource(FilePersistorFactory.getInstance().findLibrary(getProduct().getPhotos()));
	}

	@Override
	protected String getJRXML() throws Exception {
		return "ProductDetail.jrxml"; 
	}

	@Override
	protected Map getParameters() throws Exception {
		Messages errors = MapFacade.validate("Product", getView().getValues());
		if (errors.contains()) throw new ValidationException(errors);
		
		Map parameters = new HashMap();	
		parameters.put("id", (getProduct().getNumber()));
		parameters.put("description", getProduct().getDescription());
		parameters.put("author", getProduct().getAuthor().getName());
		parameters.put("isbn", getProduct().getIsbn());
		parameters.put("category", getProduct().getCategory().getDescription());
		parameters.put("price", getProduct().getPrice());
		
Collection<AttachedFile> attachedFiles = FilePersistorFactory.getInstance().findLibrary(getProduct().getPhotos()); byte[] file = attachedFiles.iterator().next().getData(); parameters.put("photoFromParameter", file);
return parameters; } private Product getProduct() throws Exception { if (product == null) { int number = getView().getValueInt("number"); product = XPersistence.getManager().find(Product.class, Integer.valueOf(number)); } return product; } }


Transcripción

Hola, soy Mónica. En esta lección aprenderás a diseñar un reporte que incluya imágenes y a enviarlas desde tu aplicación OpenXava. Veremos cómo enviar una única imagen que aparezca en los datos de cabecera, con un parámetro. Y también a enviar una colección de imágenes usando un DataSource.

Vamos a incluir imágenes en el reporte que creamos en la lección 2. Para esto debemos modificar la acción.
Primero vamos a incluir una imagen como parámetro. Declaramos una colección de AttachedFile. Esta colección la obtenemos usando findLibrary enviando el ID de la librería o galería como parámetro; este ID se encuentra en getPhotos. Si vamos a la clase Product, podemos ver que photos es un String, que es usado para guardar la llave de la librería. Y declaramos una colección de AttachedFile porque photos tiene la anotación de @Files, donde indica que puede adjuntar más de un archivo o, en este caso, imagen.
Vamos a enviar la primera imagen de la colección. Para esto, declaramos un file de tipo byte y le asignamos el getData del primer elemento de la colección. Por último, lo enviamos como parámetro.
En caso de que tengamos una anotación @File, en vez de declarar una colección de AttachedFile, sería solo uno. Y en vez de usar findLibrary, usamos solamente find para buscar el archivo adjunto enviando getPhoto como parámetro. También obtenemos la imagen con getData.
Comentamos todo lo que hicimos recién porque no usaremos @File. Ahora vamos a enviar la colección de imágenes como datasource usando lo mismo que vimos en la lección anterior. Teníamos una colección de AttachedFile, enviamos directamente eso. Listo. Ahora toca modificar el reporte.

En el reporte de ProductDetail, arrastramos un elemento Image al reporte. Vemos que hay varias formas de insertar una imagen: desde el workspace, desde nuestro sistema, usar un URL, entre otros. Dejamos la opción en "No image". Ahora creamos un parámetro para recibir la imagen. Llevará el mismo nombre que pusimos recién y como tipo de dato será object. Si no lo vemos en la lista desplegable, lo debemos buscar manualmente.
Una vez creado el parámetro, vamos a la vista source del reporte y buscamos el elemento imagen para añadirle la expresión. También lo podemos hacer directamente desde el panel de propiedades. Aquí está el elemento de la imagen. Estamos enviando un array de byte y lo recibimos como un objeto. Esto está bien. Pero ahora tenemos que interpretar ese array de bytes, por eso usamos ByteArrayInputStream, ponemos el parámetro y le aclaramos que el objeto recibido es un array de bytes.
Listo. En caso del datasource, en la clase pasada vimos que debemos acceder directamente a la propiedad de cada elemento. En este caso, data es uno de ellos. Creamos un field llamado data de tipo object. Añadimos las secciones que eliminamos anteriormente. Y arrastramos data a la sección detail. Luego en la vista source modificamos manualmente el elemento de un textField a una imagen, debemos cambiar la etiqueta de textField por image y textFieldExpression por imageExpression.
Ahora añadimos la expresión, similar a la de recién, pero usando field data. Guardamos y ordenamos los elementos del reporte. Listo, copiamos el reporte y lo probamos. Recuerda que debes iniciar de nuevo la aplicación. Al parecer está funcionando bien.

Añadí dos imágenes más para probar cómo se vería. Por defecto, las líneas de detalle se agregan una debajo de otra. Vamos a cambiar esto. Apretando fuera del reporte, podemos editar las propiedades del mismo. En Edit Page Format, cambiamos a 3 columnas y que el orden de la impresión sea horizontal. Hicimos los cambios, pero al parecer no dieron efecto. Vamos a advanced e ingresamos manualmente los valores: 3 en column count y horizontal en print order. Ahí está.
Luego seleccionamos el static text y en el panel de propiedades destildamos Print repeated Values para que no imprima el texto cada vez que se repite el elemento. Y tildamos Print in First Whole Band para que se imprima la primera vez. Copiamos y probamos de nuevo el reporte. Así serían los resultados.
En esta lección has visto dos técnicas para enviar imágenes: los parámetros y el datasource. También has aprendido a obtener las imágenes de propiedades anotadas con Files o File, aunque puedes enviar cualquier imagen obtenida de cualquier fuente como un array de bytes. Además, vimos cómo diseñar el informe para que distribuya las imágenes a nuestro gusto.

Te invitamos a que pruebes lo que has visto en la lección. Si tienes alguna duda o problema, puedes preguntarnos por el foro; también puedes descargar el código de esta lección por el link del repositorio, ambos enlaces se encuentran en la descripción del video. ¡Chao!