El componente outputChart de ICEfaces

0
9022

Índice de contenidos

  1. Introducción
  2. Preparación del entorno
  3. Creando gráficas con la etiqueta <outputchart>
  4. Generar gráficas dinámicamente
  5. Gráficas personalizadas
  6. Conclusiones

01. Introducción

ICEfaces es un entorno de representación web para aplicaciones Java Server Faces, que aumenta las capacidades del framework JSF para crear interfaces utilizando AJAX y ofrece una rica librería de componentes personalizados para mejorar la presentación de nuestras páginas.

En este tutorial nos centramos en el componente outputChart de ICEfaces, que permite la representación de gráficas circulares o de ejes. Veremos como crear gráficas utilizando la etiqueta «outputChart» en páginas JSP o por medio de código en nuestras clases Java.

Este componente utiliza internamente la librería de código abierto JCharts. Veremos también como crear gráficas más complejas con el API de JCharts y enlazarlas a componentes «outputChart».

02. Preparación del entorno

Para la realización de este tutorial se han utilizado las siguientes herramientas:

Abrimos el entorno de desarrollo y creamos un nuevo proyecto web dinámico.

Vamos a añadir el soporte para Java Server Faces, abriendo las propiedades del proyecto y seleccionando «Facetas de proyecto». Marcamos la opción para «JavaServer Faces» (y si queremos la versión 1.2).

Facetas del proyecto

En la parte inferior de la ventana nos aparece un enlace, indicando que se requiere configuración adicional. Lo pulsamos y nos aparece la siguiente ventana.

Configuración de JSF

Dejamos la implementación JSF del servidor y añadimos la librería de componentes de ICEfaces pulsando sobre el botón «new».

Librería de componentes de ICEfaces

Añadimos las siguientes librerías necesarias a la carpeta «WebContent/WEB-INF/lib». Todas estas librerías pueden encontrarse dentro de la carpeta lib de la distribución de ICEfaces que hemos descargado.

Librerías del servidor

Ahora sólamente nos resta configurar el fichero «web.xml» para añadir el soporte de ICEfaces.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         id="WebApp_ID"
         version="2.5">
  <display-name>IceFacesChart</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet>
    <servlet-name>Persistent Faces Servlet</servlet-name>
    <servlet-class>com.icesoft.faces.webapp.xmlhttp.PersistentFacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet>
    <servlet-name>Blocking Servlet</servlet-name>
    <servlet-class>com.icesoft.faces.webapp.xmlhttp.BlockingServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.faces</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>Persistent Faces Servlet</servlet-name>
    <url-pattern>*.iface</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>Persistent Faces Servlet</servlet-name>
    <url-pattern>/xmlhttp/*</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>Blocking Servlet</servlet-name>
    <url-pattern>/block/*</url-pattern>
  </servlet-mapping>

  <listener>
    <listener-class>com.icesoft.faces.util.event.servlet.ContextEventRepeater</listener-class>
  </listener>
</web-app>

 

Algunos componentes de ICEfaces, como outputChart, generan recursos (en este caso imágenes) que realmente no están almacenados en un fichero en el servidor. El Blocking Servlet recibirá las peticiones de esas imágenes, que se habrán generado dinámicamente, para que sean mostradas en la página.

El mapeo para las urls de la forma «/xmlhttp/*» también será necesario, especialmente al utilizar un actionListener disparado al pulsar sobre los elementos de las gráficas.

03. Creando gráficas con la etiqueta <outputchart>

Para comprobar que nuestra configuración es correcta vamos a crear una sencilla página de prueba, a la que llamaremos «prueba.jsp». En esta página vamos a insertar una gráfica gracias al componente «outputchart» de ICEfaces. La etiqueta <outputchart> debe ir dentro de un formulario, de lo contrario se producirá un error.

<f:view xmlns:h="http://java.sun.com/jsf/html"
        xmlns:f="http://java.sun.com/jsf/core"
        xmlns:ice="http://www.icesoft.com/icefaces/component">
  <ice:outputDeclaration doctypeRoot="HTML"
      doctypePublic="-//W3C//DTD XHTML 1.0 Transitional//EN"
      doctypeSystem="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>
  <html>
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
      <title>Prueba de outputChart</title>
    </head>
    <body>
      <ice:form>
        <ice:outputChart />
      </ice:form>
    </body>
  </html>
</f:view>

 

Si ponemos la etiqueta sin especificar ningún atributo, se utilizarán los valores por defecto. Esto nos mostrará una gráfica de barras parecida a la siguiente.

Gráfica por defecto

Como curiosidad, el color por defecto de las barras es aleatorio, y podrá cambiar si ejecutamos la aplicación varias veces.

La etiqueta «outputchart» dispone principalmente de los siguientes atributos, que nos permiten personalizar la apariencia de las gráficas.

Atributo Subtipo Valor Descripción Ejemplo Resultado Notas
type circulares «pie2d» Gráfica circular en 2 dimensiones <ice:outputCharttype=»pie2d»/> Gráfica pie2d Admite una única serie de datos
«pie3d» Gráfica circular en 3 dimensiones <ice:outputCharttype=»pie3d»/> Gráfica pie3d Admite una única serie de datos. No se muestra la leyenda, porque las etiquetas se muestran junto a cada rodaja
de ejes «area» Muestra el área rellena bajo la gráfica <ice:outputCharttype=»area» data=»40, 20, 30 : 10, 20, 10″/> Gráfica area
«areastacked» Muestra áreas apiladas (para varias series de datos) <ice:outputCharttype=»areastacked»data=»40, 20, 30 : 10, 20, 10″/> Gráfica areastacked
«bar» Diagrama simple de barras <ice:outputCharttype=»bar» data=»40, 20, 30″/> Gráfica bar
«barclustered» Muestra unas barras al lado de las otras (para varias series de datos) <ice:outputCharttype=»barclustered»data=»40, 20, 30 : 10, 20, 50 : 20, 30, 40″/> Gráfica barclustered
«barstacked» Muestra barras apiladas unas sobre otras (para varias series de datos) <ice:outputCharttype=»barstacked»data=»10, 20, 30 : 30, 30, 10″/> Gráfica barstacked
«line» Muestra puntos y líneas entre ellos <ice:outputCharttype=»line» data=»10, 20, 30 : 30, 10, 20″/> Gráfica line
«point» Muestra sólamente puntos <ice:outputCharttype=»point» data=»10, 20, 30 : 30, 10, 20″/> Gráfica point
«custom» Diagrama personalizado Ver apartado degráficas personalizadas
chartTitle String Título de la gráfica <ice:outputChart type=»pie3d»chartTitle=»TITULO»height=»200″/> Título de gráfica
labels String []
List<String>
Nombres de las etiquetas de la gráfica.
Debe haber una etiqueta por cada serie de datos o por cada valor en gráficas circulares
<ice:outputChart type=»barstacked»labels=»Uno, Dos»data=»10, 20, 30 : 20, 50, 10″ /> Gráfica con atributo labels
data double []
double [] []
List<double>
List<double []>
Valores de las series de datos.
Cada serie puede separarse con «:»
<ice:outputChart type=»barstacked» labels=»Uno, Dos»data=»38.9, 20.5 : 20, 50.0″ /> Gráfica con atributo data
colors String []
List<java.awt.Color>
Colores para las diferentes series de datos o las rodajas de los gráficos circulares. Debe haber un color por cada serie de datos o por cada valor en gráficas circulares <ice:outputChart type=»pie2d»colors=»green, red, yellow» data=»10, 20, 70″ /> Gráfica con atributo colors
height String Alto de la imagen generada (gráfcia completa, incluyendo títulos y etiquetas) en píxeles <ice:outputChartheight=»200″ /> Gráfica con atributo height
width String Ancho de la imagen generada en píxeles <ice:outputChartwidth=»200″ /> Gráfica con atributo width
legendPlacement «top», «bottom«, «left», «right», «none» Colocación de la leyenda. «none» indica que no se muestre <ice:outputChartlegendPlacement=»right»/> Gráfica con atributo legendplacement Sin efecto para el tipo «pie3d»
legendColumns Integer Número de columnas que se mostrarán en la leyenda <ice:outputChart type=»barstacked» labels=»A, B, C» data=»10 : 40 : 35″legendColumns=»2″ /> Gráfica con atributo legendColumns Sin efecto para el tipo «pie3d»
horizontal boolean Indica que las barras se muestren horizontalmente <ice:outputChart type=»bar»horizontal=»true»/> Gráfica con atributo horizontal Sólo es válido para los tipos «bar» y «barclustered»
xaxisTitle String Título del eje X <ice:outputChartxaxisTitle=»Eje X»yaxisTitle=»Eje Y»/> Gráfica con atributos xaxisTitle e yaxisTitle Válido para gráficas con ejes
yaxisTitle String Título del eje Y
xaxisLabels String []
List<String>
Rótulos del eje X. Debe haber un rótulo por cada valor de las series de datos <ice:outputChart type=»barclustered» labels=»Serie 1, Serie 2″ data=»10, 20, 30 : 15, 13, 40″xaxisLabels=»2001, 2002, 2003″/> Gráfica con atributo xaxisLabels Válido para gráficas con ejes
shapes String [] (valores «circle», «diamond», «square» o «triangle»)
List<java.awt.Shape>
Forma de los puntos para las gráficas de líneas y puntos. Debe haber tantas formas como series de datos <ice:outputChart type=»line»shapes=»circle, triangle»data=»10, 20 : 13, 19″/> Gráfica con atributo shapes Válido para tipos «line» y «point»
renderOnSubmit boolean Por defecto, la gráfica se genera una vez y vuelve a obtenerse en sucesivas peticiones. Si este valor es true, se volverá a generar la gráfica. <ice:outputChart chartTitle=»Autentia»renderOnSubmit=»true»data=»30, 40″ labels=»hola»/> Gráfica con atributo renderOnSubmit
styleClass String (por defecto «iceOutChrt» o «iceOutChrt-dis» cuando el componente está deshabilitado) Lista de clases CSS separadas por coma para el elemento. <style type=»text/css»>
.grafica {
border: 10px solid red;
float: right;}
</style>
<ice:outputChart styleClass=»grafica»/>
Gráfica con atributo styleClass
actionListener String Método que se lanzará al pulsar sobre algún elemento de la gráfica Ver apartado degráficas personalizadas

Por supuesto, además de insertar directamente los valores en las páginas JSP, podemos enlazar estos valores con propiedades de nuestros bean manejados, como con cualquier componente de JSF.

<ice:outputChart chartTitle="#{miBean.title}"
    data="#{miBean.data}"
    labels="#{miBean.labels}"
    colors="#{miBean.colors}"/>

 

04. Generar gráficas dinámicamente

Ahora que hemos visto cómo funciona la etiqueta OutputChart, vamos a ver un ejemplo de cómo generar componentes dinámicamente, a través de la clase «com.icesoft.faces.component.outputchart.OutputChart». Por medio de esta clase podemos asignar básicamente las mismas propiedades que con la etiqueta, pero desde nuestro código Java.

Creamos la clase «EjemploGraficas» que generará dos componentes de tipo OutputChart y los añadirá a un componente HtmlPanelGrid.

package backing;

import java.awt.Color;
import java.util.ArrayList;
import java.util.List;

import com.icesoft.faces.component.ext.HtmlPanelGrid;
import com.icesoft.faces.component.outputchart.OutputChart;

public class EjemploGraficas {
	
	HtmlPanelGrid panel = new HtmlPanelGrid();

	/* A�adir graficas al panel */
	public EjemploGraficas() {
		panel.getChildren().add(getEjemplo1());
		panel.getChildren().add(getEjemplo2());
	}
	
	/* Generar grafica circular */
	public OutputChart getEjemplo1() {
		OutputChart outputChart = new OutputChart();

		outputChart.setChartTitle("Tutoriales en Autentia");
		outputChart.setType("pie2d");
		outputChart.setData(new double [] {180.0, 76.0, 42.0, 28.0});
		outputChart.setLabels(new String [] {"Roberto", "Alejandro", "Carlos", "Francisco Javier"});
		outputChart.setColors(new String [] {"green", "blue", "cyan", "yellow"});
		outputChart.setLegendPlacement("right");
		outputChart.setLegendColumns(1);
		
		return outputChart;
	}
	
	/* Generar grafica con ejes */
	public OutputChart getEjemplo2() {
		OutputChart outputChart = new OutputChart();
		List<Color> colores = new ArrayList<Color>();

		outputChart.setChartTitle("Prueba con ejes");
		outputChart.setType("barclustered");
		outputChart.setData(new double [] [] {new double [] {180.0, 76.0, 42.0, 28.0},
				                               new double [] {120.0, 30.0, 10.0, 25.0},
				                               new double [] {100.0, 40.0, 13.0, 56.0}});
		outputChart.setLabels(new String [] {"Serie 1", "Serie 2", "Serie 3"});
		colores.add(new Color(26, 86, 138));
		colores.add(new Color(200));
		colores.add(new Color(100));
		outputChart.setColors(colores);
		outputChart.setXaxisLabels(new String [] {"L1", "L2", "L3", "L4"});
		outputChart.setXaxisTitle("Eje X");
		outputChart.setYaxisTitle("Eje Y");
		
		return outputChart;
	}

	public HtmlPanelGrid getPanel() {
		return panel;
	}

	public void setPanel(HtmlPanelGrid panel) {
		this.panel = panel;
	}
}

 

Modificamos el fichero «faces-config.xml» para añadir un bean manejado de la clase anterior.

<managed-bean>
  <managed-bean-name>ejemploGraficas</managed-bean-name>
  <managed-bean-class>backing.EjemploGraficas</managed-bean-class>
  <managed-bean-scope>request</managed-bean-scope>
</managed-bean>

 

Modificamos «prueba.jsp» de forma que sólamente contenga un panel enlazado a la propiedad «panel» de nuestro bean manejado.

<ice:form>
  <ice:panelGrid binding="#{ejemploGraficas.panel}" columns="2" />
</ice:form>

 

Cuando se muestre la JSP se ejecutará el constructor de nuestra clase, el cual añadirá las gráficas al panel. El resultado será el siguiente:

Visualización de las gráficas

05. Gráficas personalizadas

Con lo visto hasta ahora podemos generar un amplio abanico de gráficas, personalizando casi todas sus características importantes. Pero en ocasiones, puede que eso no sea suficiente.

Si queremos generar algo más complejo como, por ejemplo, varios tipos diferentes de series (barras, líneas, áreas…) en una misma gráfica, podemos hacerlo utilizando directamente el API de «jCharts», sobre el que se apoya el componente «outputChart». De esta manera podremos generar cualquier gráfica que pueda generarse con «jCharts» y después enlazarla con nuestro componente visual.

Vamos a ver un ejemplo en el que generaremos una gráfica con series de datos que incluyan barras y líneas. Además, veremos cómo utlizar la propiedad «actionListener» del componente para disparar un evento al pulsar sobre algún valor de la gráfica.

Creamos la clase «EjemploJChart» dentro del paquete «backing»:

package backing;

import java.awt.Color;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.Stroke;

import javax.faces.event.ActionEvent;

import org.krysalis.jcharts.axisChart.AxisChart;
import org.krysalis.jcharts.chartData.AxisChartDataSet;
import org.krysalis.jcharts.chartData.DataSeries;
import org.krysalis.jcharts.properties.AxisProperties;
import org.krysalis.jcharts.properties.ChartProperties;
import org.krysalis.jcharts.properties.ClusteredBarChartProperties;
import org.krysalis.jcharts.properties.LegendProperties;
import org.krysalis.jcharts.properties.LineChartProperties;
import org.krysalis.jcharts.properties.PointChartProperties;
import org.krysalis.jcharts.types.ChartType;

import com.icesoft.faces.component.outputchart.OutputChart;

public class EjemploJChart {

	// Valores del elemento pulsado en la grafica por el usuario
	private String valor;

	// Grafica generada con jCharts, enlazada al componente
	private static AxisChart grafica;

	/* Evento disparado cuando el usuario pulse sobre un elemento de la grafica */
	public void areaPulsada(ActionEvent event) {
		OutputChart chart    = (OutputChart) event.getSource();
		
		// Recuperamos los valores del elemento pulsado
		String      leyenda  = chart.getClickedImageMapArea().getLengendLabel();
		String      etiqueta = chart.getClickedImageMapArea().getXAxisLabel();
		double      valor    = chart.getClickedImageMapArea().getValue();

		// Cambiamos el valor del texo a mostrar
		this.valor = leyenda + " (" + etiqueta + ") = " + valor;
	}

	/*
	 * Indica cuando debe representarse nuevamente la grafica. Recibe el
	 * componente a representar.
	 */
	public boolean actualizar(OutputChart component) {
		if (grafica == null || component.getChart() == null) {
			generarGrafica();
			// Asignamos la grafica personalizada al componente
			component.setChart(grafica);

			return true;
		}

		return false;
	}

	/*
	 * Construye una grafica utilizando jCharts. La grafica tendra dos conjuntos
	 * de datos diferentes, uno de barras y otro de lineas
	 */
	private void generarGrafica() {
		try {
			/********** Se establecen las propiedades generales del diagrama **********/
			String [] etiquetasX    = { "Enero", "Febrero", "Marzo" };
			String    tituloX       = "Mes";
			String    tituloY       = "Euros";
			String    tituloGrafica = "Gastos e ingresos";
			/**************************************************************************/

			DataSeries series = new DataSeries(etiquetasX, tituloX, tituloY,
					tituloGrafica);

			/********** Se construye el primer conjunto de datos (barras) **********/
			String [] leyenda = { "Sueldo", "Extras", "Tickets" };
			Paint  [] colores = new Color[] { new Color(0xFF5566),
					new Color(0x00FFFF), new Color(0xFFFF00) };
			double[][] datos = { { 1700, 1900, 1900 }, { 120, 220, 230 }, {180, 160, 189} };

			AxisChartDataSet axisChartDataSet = new AxisChartDataSet(datos,
					leyenda, colores, ChartType.BAR_CLUSTERED,
					new ClusteredBarChartProperties());
			series.addIAxisPlotDataSet(axisChartDataSet); // Se a�ade la serie
			/********************************************************************************/

			/********** Se construye el segundo conjunto de datos (lineas) **********/
			leyenda = new String[] { "Vivienda", "Transporte" };
			colores = new Paint[] { new Color(0x445566), new Color(0xAABBCC) };
			datos   = new double[][] { { 1000, 1100, 1150 }, { 400, 560, 700 } };

			Stroke[] estiloLineas = { LineChartProperties.DEFAULT_LINE_STROKE,
					LineChartProperties.DEFAULT_LINE_STROKE };
			Shape[] estiloPuntos = { PointChartProperties.SHAPE_CIRCLE,
					PointChartProperties.SHAPE_SQUARE };

			axisChartDataSet = new AxisChartDataSet(datos, leyenda, colores,
					ChartType.LINE, new LineChartProperties(estiloLineas, estiloPuntos));
			series.addIAxisPlotDataSet(axisChartDataSet); // Se a�ade la serie
			/************************************************************************/

			/********** Se construye la grafica, con propiedades por defecto **********/
			grafica = new AxisChart(series, // Series de datos anteriores
					new ChartProperties(), // Propiedades de la grafica (por defecto)
					new AxisProperties(), // Propiedades de los ejes (por defecto)
					new LegendProperties(), // Propiedades de la leyenda (por defecto)
					400, // Ancho de la grafica
					500); // Alto de la grafica
			/*********************************************/
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public String getValor() {
		return valor;
	}

	public void setValor(String valor) {
		this.valor = valor;
	}
}

 

Esta clase genera una gráfica de ejemplo que presenta gastos e ingresos a lo largo de un trimestre. Las series de gastos se representan con líneas, mientras que las de ingresos lo hacen mediante barras verticales. Por simplicidad se han añadido únicamente dos o tres series de cada tipo.

El método actualizar es el que realiza la generación de la gráfica cuando ésta aún no se ha inicializado, e irá enlazado con la propiedad «renderOnSubmit» del componente. Cuando se vaya a visualizar el componente se llamará a este método y, si es la primera vez, se generará la gráfica.

Es importante notar que podemos tener diferentes conjuntos de datos, pero en cada uno debe cumplirse lo siguiente:

  • La cardinalidad de «leyenda», «colores» y «datos» debe ser la misma, ya que se refieren a una misma serie.
  • La cardinalidad de cada uno de los elementos de «datos» debe coincidir a su vez con el número de etiquetas en el eje X.

Modificamos el fichero prueba.jsp para mostrar un texto que indicará el valor pulsado sobre la gráfica y la propia gráfica:

<ice:outputText value="Valor pulsado: #{ejemploJChart.valor}"></ice:outputText>
<ice:outputChart id="outputChart"
                 type="custom"
                 renderOnSubmit="#{ejemploJChart.actualizar}"
                 actionListener="#{ejemploJChart.areaPulsada}" />

 

También debemos añadir el nuevo bean manejado dentro del fichero «faces-config.xml».

<managed-bean>
  <managed-bean-name>ejemploJChart</managed-bean-name>
  <managed-bean-class>backing.EjemploJChart</managed-bean-class>
  <managed-bean-scope>request</managed-bean-scope>
</managed-bean>

 

Compilamos y publicamos nuestros cambios, y arrancamos de nuevo el servidor. El resultado será una gráfica como la siguiente:

Gráfica personalizada

Si pulsamos sobre un elemento de la gráfica, veremos que se actualiza el texto de la parte superior:

Mensaje actualizado

06. Conclusiones

Las conclusiones que podemos extraer de este tutorial son las siguientes:

  • Podemos utilizar el componente outputChart para crear gráficas de forma rápida y sencilla en nuestras páginas JSF.
  • El componente outputChart dispone de bastantes propiedades que nos permiten configurar los datos y la apariencia de las gráficas a mostrar.
  • Podemos manejar los eventos que se producen al pulsar sobre los elementos de nuestras gráficas para realizar acciones, como mostrar información ampliada, abrir otras páginas o cualquier cosa que se nos ocurra.
  • Si necesitamos gráficas más sofisticadas, podemos utilizar el API de JCharts para crearlas y enlazarlas a componentes outputChart para obtener todas las ventajas que nos ofrecen JSF e ICEfaces.

Y eso es todo. Desde Autentia os animamos a utilizar este componente si necesitáis utilizar gráficas en vuestras aplicaciones, lo cual mejorará notablemente la presentación y permitirá tener un interfaz más intuitivo y amigable para los usuarios.

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad