Como generar un PDF con datos de una tabla MySQL con ayuda de iText

Ejemplo muy sencillo donde se ilustra como generar un documento PDF con datos provenientes de una tabla creada en MySQL con la libreria iText. Bueno creo que el titulo de la entrada lo dice todo asi que no quiero ser redundante en el objetivo de esta practica de programacion.

El ejemplo consta de 3 archivos: CrearConexion.java, GenerarPDFEmpleados.java JfrPrincipal.java (a decir verdad tambien se usa una imagen (logo de mysql), pero puedes cambiarla por otra que quieras). Como en casi todos mis ejemplos, no voi a dar mucha explicacion debido a que mi objetivo es tener disponible el ejemplo de codigo. Primero que nada te muestro un diagrama para que veas en forma grafica y rapida la estructura del ejemplo:

Diagrama que muestra en forma grafica el ejemplo

Diagrama que muestra en forma grafica el ejemplo

A continuacion se explican brevemente los tres archivos de codigo a grandes rasgos:

JfrPrincipal
Clase que crea una interfaz grafica de usuario muy sencilla; la cual es una ventana con 2 JLabels, un JTextField y un JButton. Desde esta clase se hace una instancia de la clase GenerarPDFEmpleados.java, la cual es la que realmente genera el PDF con ayuda de la libreria iText. En el codigo se muestran los comentarios correspondiente explicando casi todo…

/*
		Instituto Tecnologico de Zacatepec, Mor.
Descripcion:  Clase que crea una ventana con un boton que al darle clic
					genera el PDF de una tabla de MySQL.
Autor:  			Gonzalo Silverio   gonzasilve@gmail.com
Archivo: 		JfrPrincipal.java
*/

import javax.swing.*;
import java.awt.FlowLayout;
import java.awt.event.*;

public class JfrPrincipal extends JFrame
{
	String strTituloPDF = "INSTItuTO TEcnologico de zacatepec";
	String strNombrePDF = "pdf_tabla_Empleados.pdf";
	JTextField jtfNombrePDF;
	
	//Constructor
	JfrPrincipal(String titulo, int ancho, int alto)
	{
		//Establecer titulo, tamanio y posicion en la pantalla
		super(titulo);
		setSize(ancho,alto);
		setLocationRelativeTo(null);	//centrado
		//Rotulo principal de la ventana
		JLabel lblTitulo = new JLabel("Generar un PDF desde Java");
		JPanel panTitulo = new JPanel(new FlowLayout(FlowLayout.CENTER));
		panTitulo.add(lblTitulo);
		
		//Crea campo de texto para especificar el nombre del PDF
		JLabel lblNombrePDF = new JLabel("Nombre del documento PDF");
		jtfNombrePDF = new JTextField(30);
		jtfNombrePDF.setText(strNombrePDF);
		jtfNombrePDF.setHorizontalAlignment (JTextField.CENTER);
		JPanel panNombrePDF = new JPanel(new FlowLayout(FlowLayout.CENTER));
      panNombrePDF.add(Box.createHorizontalStrut(15));
		panNombrePDF.add(lblNombrePDF);
		panNombrePDF.add(jtfNombrePDF);
		
		//Crear el boton nuevo
		JButton btnGenerarPDF = new JButton("Generar PDF");
		JPanel panGenerarPDF = new JPanel(new FlowLayout(FlowLayout.CENTER));
		panGenerarPDF.add(btnGenerarPDF);

		//Todos los componentes estan en un Box Vertical
		//la clase Box se usa para alinear los controles
		Box boxVertical = Box.createVerticalBox();
		boxVertical.add(Box.createVerticalStrut(50));
		boxVertical.add(panTitulo);
		boxVertical.add(panNombrePDF);
		boxVertical.add(Box.createVerticalStrut(10));
		boxVertical.add(panGenerarPDF);

		//Agregar el Box a la ventana
		add(boxVertical);
		setResizable(false);	//No maximizar ni cambiar tamanio
		//Al dar en la X terminar todo el programa
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    	// ########### ESCUCHADOR BOTON NUEVO   ##########
    	ActionListener escuchadorGenerarPDF = new ActionListener()
    	{
        	public void actionPerformed(ActionEvent evt)
        	{
        		strNombrePDF = jtfNombrePDF.getText();
            GenerarPDFEmpleados ejemplo = new GenerarPDFEmpleados(strTituloPDF,strNombrePDF);
       		//Preguntar al usuario si desea abrir el documento PDF
       		int respuesta = JOptionPane.showConfirmDialog(null,"Se ha generado el documento "+strNombrePDF+", ¿Desea abrirlo?","Pregunta",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE);
       		//Si la respuesta es SI, abrirlo
				if(respuesta == JOptionPane.YES_OPTION)
					ejemplo.abrirPDF ();
          
        	}
   	};
    	btnGenerarPDF.addActionListener(escuchadorGenerarPDF);

    	
	}	//Fin del constructor

	//hace visible la ventana	
	public void mostrar()
	{
		setVisible(true);
	}

	public static void main(String[] args) 
   {
		JfrPrincipal ejemplo = new JfrPrincipal("Ventana principal de Usuario",400,400);
		ejemplo.mostrar();
   }
}

Y a continuacion una imagen de la GUI que se genera:

GUI para el ejemplo

GUI para el ejemplo

El primer Jlabel es un rotulo para la ventana, el segundo Jlabel es una etiqueta para el JTextField con la cual se le indica al usuario que debe escribir el nombre del documento PDF (con extension), el JTextField es el campo donde el uuario debe escribir el nombre del PDF. El JButton al darle click; el usuario generara el documento PDF de una tabla llamada Empleados e inmediatamente se le preguntara si desea abrirlo, aca una imagen:

Pregunta al usuario si desea abrir el PDF

Pregunta al usuario si desea abrir el PDF


Si el usuario da click en el boton Si del mensaje llama al metodo abrirPDF() de un objeto de la clase GenerarPDFEmpleados.java el cual abrira en una nueva ventana el documento PDF dentro del cual se muestra el contenido de la tabla empleados, aca una imagen del PDF:
PDF generado con datos de tabla empleados creada en MySQL

PDF generado con datos de tabla empleados creada en MySQL

GenerarPDFEmpleados.java
En esta clase es donde se hace uso de la libreria iText para generar un documento PDF. El codigo de esta clase es el siguiente:


//		Instituto Tecnologico de Zacatepec
//  	Descripcion:  Programa que genera un archivo PDF con datos de una base de datos
//		en mySQL y con ayuda de la libreria iText
//  	Author: Gonzalo Silverio   gonzasilve@hotmail.com
//		Archivo: GenerarPDFEmpleados.java

import java.awt.Color;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;

import com.lowagie.text.Anchor;
import com.lowagie.text.BadElementException;
import com.lowagie.text.Cell;
import com.lowagie.text.Chapter;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.List;
import com.lowagie.text.ListItem;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Section;
import com.lowagie.text.Table;
import com.lowagie.text.Element;
import com.lowagie.text.PageSize;

import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfWriter;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPTable;

import com.lowagie.text.Image;

import java.sql.*;

public class GenerarPDFEmpleados
{
	private String strNombreDelPDF;

	private  Font fuenteNegra10 = new Font(Font.TIMES_ROMAN, 10, Font.BOLD, Color.BLACK);
	private  Font fuente8 = new Font(Font.TIMES_ROMAN, 8, Font.NORMAL, Color.BLACK);
	private  Font fuenteAzul25 = new Font(Font.TIMES_ROMAN, 25, Font.BOLD, Color.BLUE);

	Color grisClaro = new Color( 230,230,230);	
	Color azulClaro = new Color( 124,195,255 );

	//############# VARIABLES PARA MANEJO DE BASE DE DATOS ########################
	//Guarda la consulta operacion a realizar
	String strConsultaSQL;
	//Apuntador a la conexion
	Connection conn = null;	
	//Para ejecutar operaciones SQL
	Statement estSQL1;
	//Para guardar los resultados de una operacion SELECT
	ResultSet rs;
	Document document;
	PdfWriter writer;
	String strRotuloPDF;
	
	//Metodo principal del ejemplo
	public GenerarPDFEmpleados(String titulo, String nomPDF)
	{
		strRotuloPDF = titulo;
		strNombreDelPDF = nomPDF;
		try 
		{		//Hoja tamanio carta, rotarla (cambiar a horizontal)
			document = new Document( PageSize.LETTER.rotate() );
			
			writer = PdfWriter.getInstance(
			// that listens to the document
					document,
					// direccionar el PDF-stream a un archivo
					new FileOutputStream(strNombreDelPDF));
			document.open();

			agregarMetaDatos(document);
			agregarContenido(document);
			
			document.close();
			
			System.out.println("Se ha generado el PDF: "+ strNombreDelPDF);
				
		} catch (Exception e) 
		{
			e.printStackTrace();
		}
	}
	
	//agrega el contenido del documento; para este ejemplo agrega una tabla con datos y una imagen
	//Espera como entrada el documento donde agregara el contenido
	private void agregarContenido(Document document) throws DocumentException
	{
		Paragraph ParrafoHoja = new Paragraph();
				
		// Agregamos una linea en blanco al principio del documento
		agregarLineasEnBlanco(ParrafoHoja, 1);
		// Colocar un encabezado (en mayusculas)
		ParrafoHoja.add(new Paragraph(strRotuloPDF.toUpperCase (), fuenteAzul25) );
		agregarLineasEnBlanco(ParrafoHoja, 1);
		// 1.- AGREGAMOS LA TABLA
		agregarTabla(ParrafoHoja);
		//Agregar 2 lineas en blanco
		agregarLineasEnBlanco(ParrafoHoja, 2);
		// 2.- AGREGAMOS LA IMAGEN
		try
		{
			Image im = Image.getInstance("logo_mysql.gif");
			im.setAlignment(Image.ALIGN_CENTER | Image.TEXTWRAP );
			im.setWidthPercentage (50);
	      ParrafoHoja.add(im);
		}
		catch(Exception e)
		{
			e.printStackTrace ();
		}
		
		document.add(ParrafoHoja);

	}

	//Se conecta al DBMS MySQL , obtiene los datos de la tabla (SELECT) y los acomoda en una tabla JTable de iText.
	// Espera como entrada el parrafo donde agregara la tabla
	private void agregarTabla(Paragraph parrafo) throws BadElementException 
	{
		//Anchos de las columnas
		float anchosFilas[] = { 0.2f,1f,1f,0.5f,0.5f,0.3f,1f,1.5f,0.7f };
		PdfPTable tabla = new PdfPTable(anchosFilas);
		String rotulosColumnas[] = {"id","Nombre","Apellidos","Sexo","Telefono","Edad","Correo","Direccion","Fecha\nContratacion"};
		// Porcentaje que ocupa a lo ancho de la pagina del PDF
		tabla.setWidthPercentage(100);
		//Alineacion horizontal centrada
		tabla.setHorizontalAlignment(Element.ALIGN_CENTER);
		//agregar celda que ocupa las 9 columnas de los rotulos
		PdfPCell cell = new PdfPCell(new Paragraph("Tabla: Empleados"));
		cell.setColspan(9);
		//Centrar contenido de celda
		cell.setHorizontalAlignment(Element.ALIGN_CENTER);
		//Color de fondo de la celda
		cell.setBackgroundColor (azulClaro);		
		tabla.addCell(cell);

    	try
    	{
			if ( ConectarBD() )
			{
				// Mostrar los rotulos de las columnas
				for(int i=0; i<rotulosColumnas.length; i++)
				{
					cell = new PdfPCell(new Paragraph(rotulosColumnas[i],fuenteNegra10));
					cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
					cell.setHorizontalAlignment(Element.ALIGN_CENTER);
					cell.setBackgroundColor (grisClaro);
					tabla.addCell(cell);
				}
				
				//Consultar la tabla empleados
				strConsultaSQL = "SELECT * FROM empleados";
				//ejecutar consulta
				rs = estSQL1.executeQuery(strConsultaSQL);

				//Iterar Mientras haya una fila siguiente
	   		while (rs.next())
	   		{			//Agregar 9 celdas
					cell = new PdfPCell(new Paragraph(String.valueOf(rs.getInt ("idEmpleado")),fuente8 ));
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(rs.getString("nombre"),fuente8));
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(rs.getString("apellidos"),fuente8));
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(rs.getString("sexo"),fuente8));
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(rs.getString("telefono"),fuente8));
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(String.valueOf(rs.getInt("edad")),fuente8) );
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(rs.getString("correo"),fuente8));
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(rs.getString("direccion"),fuente8));
					tabla.addCell(cell);
					cell = new PdfPCell(new Paragraph(rs.getDate("fechaContratacion").toString (),fuente8 ) );
					tabla.addCell(cell);
   			}
   			
	        	//Cerrar los objetos de manejo de BD
	        	CrearConexion.cerrar(rs);			//ResultSet
	        	CrearConexion.cerrar(estSQL1);	//Statement
	        	CrearConexion.cerrar(conn);		//Connection
			}		//Fin de if que comprueba si se pudo conectar
			
		}
		catch(Exception e) 
		{
	    	System.out.println("Excepcion al ejecutar CONSULTA!!!");
	    	//Mostrar la traza de la pila
	    	e.printStackTrace();
		}
		//Agregar la tabla con los datos al parrafo que nos llego como entrada
		parrafo.add(tabla);
	}  //Fin del metodo que crea la tabla

	//Agrega las lineas en blanco  especificadas a un parrafo especificado
	private static void agregarLineasEnBlanco(Paragraph parrafo, int nLineas) 
	{
		for (int i = 0; i < nLineas; i++) 
			parrafo.add(new Paragraph(" "));
	}
	
	//Agrega los metadatos del documento, los metadatos a asignar son
	//Titulo, Asunto, Palabras clave, Autor y el sw o org con el cual fue generado
	private static void agregarMetaDatos(Document document)
	{
		document.addTitle("Documento con datos de tabla MySQL");
		document.addSubject("Usando iText y MySQL");
		document.addKeywords("Java, PDF, iText");
		document.addAuthor("Gonzalo Silverio");
		document.addCreator("https://gonzasilve.wordpress.com");
	}

	//devuelve true en caso de que si se pudo conectar
	//devuelve false sino se logro conectar
	public boolean ConectarBD() throws Exception
	{
	    try
	    {		
	    		//Aqui se instancia a la otra clase --> CrearConexion.java	    		
	    		//y se le mandan en el constructor los datos de conexion
	     		CrearConexion con  = new CrearConexion("root","root","prueba");
	     		//Obtiene una referencia a la conexion abierta
	     		conn = con.getConnection();
	      	
	      	//Comprobar si hay una refencia valida
	      	if(conn!=null)
	      	{
					//Mostrar MSG al usuario de la conexion se ha establecido
					System.out.println("Conexion establecida");
	     			//Se prepara para ejecutar sentencias en la conexion recien abierta
	      		estSQL1 = conn.createStatement();
					return true;
	      	}
	      	else
	      		return false;
	      		
	  	 }
	    catch (SQLException e)
	    {
	    	
	      // the above drop statements will throw exceptions
	      // if the types and tables did not exist before. Just ingore it.
	      System.out.println("Error en la conexion!!!");
	      e.printStackTrace();
	      return false;
	    }
	    		
	}
	
	//Abre el documento PDF
	public void abrirPDF()
	{
  		/* Abrir el archivo PDF */
		try 
		{
			Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + strNombreDelPDF);
		}
		catch (IOException e) 
		{
			e.printStackTrace();
		}	
	}	
}

Como se observa en el metodo conectarBD() se hace una instancia de la clase CrearConexion.java y se le mandan en el constructor los datos con los que se conectara a MySQL.

Los datos que se usan para conectarse al DBMS son:
Usuario: root
Password: root
Base de datos: prueba
Tabla: empleados
Host: localhost

Y la estructura de la tabla empleados es:

Estructura de la tabla empleados usada en este ejemplo

Estructura de la tabla empleados usada en este ejemplo

CrearConexion.java
Este archivo tiene como funcion la apertura de una conexion al DBMS MySQL y devuelve la referencia a traves de su metodo getConnection(). En el constructor recibe los datos que seran usados por el JConnector, el codigo de este archivo es:

// 		Instituto Tecnologico de Zacatepec
 // Descripcion: Clase para manejo de base de datos de MySQL
 // Author Gonzalo Silverio    gonzasilve@hotmail.com
 // Archivo: CrearConexion.java


import java.sql.*;

public class CrearConexion 
{
	//Datos por default de la conexion
	static String strUsuario = "usr";
	static String strPassword = "pw";
	static String strBaseDatos ="bd";
	static String strHost = "localhost";
	
	//Constructor, le llegan los datos con los que se conectara al DBMS
	public CrearConexion(String usr,String pw, String bd)
	{
		strUsuario = usr;
		strPassword = pw;
		strBaseDatos =bd;
		try
		{
			Class.forName("com.mysql.jdbc.Driver");		
		} catch ( ClassNotFoundException e )
		{
			System.out.println("ERROR: Error al cargar la clase del Driver");		
		}
	}
	
	//Constructor, le llegan los datos con los que se conectara al DBMS
	// a dif. del otro constructor le llega tbn el host (servidor)
	public CrearConexion(String usr,String pw, String bd,String srvr)
	{
		strUsuario = usr;
		strPassword = pw;
		strBaseDatos =bd;
		strHost = srvr;
		try
		{
			//Cargar el driver
			Class.forName("com.mysql.jdbc.Driver");		
		} catch ( ClassNotFoundException e )
		{
			System.out.println("ERROR: Error al cargar la clase del Driver\n");
			e.printStackTrace();
		}
	}
	
	public static Connection getConnection() throws SQLException 
	{
		//a continuacion vamos a formar la cadena de conexion, pero...
		//OJO aca debes poner el nombre de la instancia de SQL Server que vas a usar
		String url = "jdbc:mysql://"+strHost+"/"+strBaseDatos;
		return DriverManager.getConnection(url,strUsuario,strPassword);
	}

	//Cierra objeto Resultset
	public static void cerrar(ResultSet rs)
	{	
		try
		{
			rs.close();
		} 
		catch(Exception ex)
		{}
	}
	
	//Cierra objeto Statement
	public static void cerrar(Statement st)
	{
		try
		{
			st.close();
		} 
		catch(Exception ex)
		{}
	}
	
	//Cierra objeto Connection
	public static void cerrar(Connection con)
	{	
		try
		{
			con.close();
		} 
		catch(Exception ex)
		{}
	}
}	//Fin de la clase

Como se puede ver esta clase es la misma que use en el ejemplo Acceso a Base de datos de SQL Server desde java (Jconnector).

Eso es todo, hasta pronto y espero comentarios al respecto. ya sabes si quieres los fuentes, basta con pedirlos dejando tu mail. Suerte, bye.

Acerca de gonzasilve
Freelance Web Developer.

133 Responses to Como generar un PDF con datos de una tabla MySQL con ayuda de iText

  1. Monica Lopez says:

    Hola, me ayudó en mucho tu proyecto 🙂
    … podrás ayudarme con una pregunta:

    me marca error mi clase de GenerarPDF en la línea en la que declaro mi metodo principal.
    –Por favor, necesito que me ayudes

    espero respuesta :3

  2. andres says:

    Hola amigo me podrias mandar el ejemplo para ver su funcionamiento ??
    muchas gracias!!

  3. Buenas que tal amigo, como seria para imprimir directamente con la impresora predeterminada, osea en vez de abrir el pdf que me lo imprima ya.

  4. Hola! me pueden ayudar con el proyecto?, quisiera saber si es posible mandarlo a mi correo: Mazinkaiser_SRW@hotmail.com. Gracias!!!!

  5. Said says:

    Hola, el codigo se me hace muy bueno, sin embargo, me podrias ayudar? tienes idea de como se podria generar a partir de una conexion mysql pero via jpa?

  6. Me gustaría el fuente ya que es muy bueno

  7. Jonnathan Peña says:

    Buenas amigo, serías tan amable de enviarme la libreria que utilizaste a razaisger@hotmail.com

  8. oscar manuel says:

    Hola, este metodo se ve interesante; me gustaria tener las fuentes para verificar si sirve a mis propositos. Saludos

  9. eduardo hernandez says:

    Que tal amigo buen ejemplo, de casualidad podrias enviarme para poder ver bien su funcionamiento. jonystanlita5@gmail.com

  10. que paso con tu imagenes amigo! x si tambien me lo puedes enviar te lo agradecere mucho.

  11. harby says:

    me podrías regalar el proyecto a este correo: harbyjohaan@hotmail.com gracias

  12. german melchor says:

    pasame el programa porfa germanmelchorv@gmail.com

  13. josse says:

    Te pido un favor si me puedes pasar tu código y las librerías que utilizaste mi correo es ani.963@hotmail.com

  14. Breth Solares says:

    Amigo Tengo una duda con tu codigo.. Podrias Respondermela Porfavor.. Te lo agradecera Mucho

  15. Ryokaizadi says:

    k tal sera que me puedes propprcionar el programa porfaz te
    dejo mi correo: drinkit_18@hotmail.com

  16. vere says:

    y si quiero solo enviar los datos sin la tabla?

  17. Jose says:

    Me puedes enviar el proyecto esta muy bueno quiero ver como funciona
    mi correo j.carocaanticoy@gmail.com

  18. Lalo says:

    me pasarias el codigo fuente usando la libreria este es mi correo cobra_1884@hotmail.com

  19. Pedro Cardenas Del Angel says:

    pasame tambien el codigo fuente de la aplicacion
    mi correo es cardenas_clk@hotmail.com

  20. nastick says:

    Excelente aporte, me podrias enviar el codigo por favor. nastick.nes@gmail.com
    Gracias.
    Saludos.

  21. Maria Dolores says:

    Hola muchas gracias por el aporte, es justo lo que estaba buscando. Te molestaria si te pido que me lo puedas compartir?
    Muchas gracias de antemano!!
    Mi correo es transparente_29@hotmail.com

  22. Chipo says:

    Muchísimas gracias gonzasilve es lo que estaba buscando. Empecé a ver hoy cómo hacer reportes desde Java y estaba entre las herramientas IText y el jasperReports, pero con este tutorial me voy a inclinar por IText, todavía no sé bien por qué, creo que es porque me gusta complicarme siempre la vida, pero creo que al ser todo por código es más «configurable». Me interesaría mucho conocer tu opinión al respecto que sos el que sabe.
    Abrazo!

  23. agustin says:

    Muy bueno!!
    me lo puedes enviar?
    muchas gracias y saludos!

  24. agustin says:

    Muy bueno!! me lo puedes enviar?
    muchas gracias y saludos!

  25. Sandra says:

    Hola muy bueno el tutorial podrias mandarme el ejemplo?, me gustaria verlo para poder ver como funciona.. gracias..

    sandy_diazv@hotmail.com

  26. hola amigo me podrias envia el proyecto, la verdad muy interesante creo ke e leido todos los codigos que has publicado =)

    pankexiito@gmail.com

  27. John says:

    amigo muy buen post me pudes pasar tu proyecto para ver como funciona y asi practicar

  28. CRISTIAN MEJIA SUAREZ says:

    muy interesante… me puedes enviar el proyecto porfavor… cristianmejiasuarez@gmail.com Gracias por compartir!

  29. Porfas el codigo me seria muy util! Y sigue adelante!

  30. Samuel Fuentes says:

    buen post amigo, pero me podrias mandar el proyecto porfa, es que estoy hace tiempo tratando de hacer estoy y no me resulta, porfa me harias un gran favor, mi correo es shamxel_988@hotmail.com

  31. Juan says:

    Excelente!!
    Me podrias enviar el proyecto a mi tambien?
    Por favor!!

  32. normilla says:

    hola buenas tardes necesito mucho de favor si me podrías pasar el proyecto completo mi correo es normix.osunadelreal5@gmail.com
    graciiias! *:)

  33. Anthony says:

    Excelente aporte gonzasilve gracias por compartir me pordrias enviar el ejemplo para analizarlo y sigue asi, saludos desde Perú.

  34. JesL says:

    PD: masterofmusic@live.com.mx
    este es mi correo… gracias!

  35. JesL says:

    Hola que tal estoy viendo el tutorial y me parece perfecto… podrian enviarme por favor el ejemplo para correrlo en mi equipo?.

  36. Randy says:

    Buena , me solucionaste una duda

  37. Camilo says:

    Me sumo a Martin, excelente ejemplo, me puedes enviar el proyecto, saludos

  38. martin says:

    Como siempre los mejores Tutoriales…
    Podrias mandarme este ejemplo para poder ver como funciona?
    tubidj@hotmail.com

    muchas gracias
    saludos

Deja un comentario