Heyyyyyyyyyyyyyyy

Aprende a programar microcontroladores en C... http://tecdigitaldelbajio.com/software-tarjeta.html

miércoles, 13 de enero de 2010

Ejemplo #16 Graficando la función seno en el celular

-->

Hoy se mostrará una aplicación practica de los arreglos, el ejemplo que se mostrará en este post tiene como objetivo graficar la función seno así que iniciemos.

La función seno

Como siempre se inicia recurriendo a la WikiPedia para conocer detalles de esta función da clic aquí para que veas el articulo de esta función. En la siguiente imagen se muestra la gráfica de la función, que a final de cuentas es lo que deseamos graficar en el celular:




Dos cosas, una la grafica en el eje de las y’s solo toma valores de 1 y de -1, y la otra, solo se graficará un ciclo completo de la función como en la figura, esto implica que se va a graficar en las x’s solo de 0 a 360 grados, esto se debe tomar en cuenta para realizar el programa.


Programa
Enseguida se da la explicación del código Java para que se muestre la grafica deseada, pero cabe mencionar que solo se muestra la parte que va en el método paint(), como crear los códigos para el proyecto ya se ha mencionado en los post anteriores a este, y creo yo, que ya no es necesario repetirlo.

Dibujando los ejes
Se inicia la gráfica dibujando los ejes coordenados, son simples dos líneas como se puede observar en la figura anterior. Para saber con exactitud el número de pixeles que tiene la pantalla del celular y además, para que el programa que se diseñe, funcione con cualquier tipo de pantalla así tenga más pixeles en una que en otra vamos a obtener el ancho y el alto en pixeles así:

ancho = getWidth();
alto = getHeight();
Obviamente que las variables que yo invente: ancho y alto, previamente se tuvieron que declarar de tipo entero. Recuerde las coordenadas que usa Java en la pantalla del celular son así: esquina superior izquierda (0,0), esquina inferior izquierda (0, alto), esquina superior derecha: (0, ancho) y esquina inferior derecha (ancho, alto)

Entonces basta con dos instrucciones que dibujan líneas para crear los ejes en color rojo así:

g.setColor(0xFF, 0x00, 0x00); // Rojo
g.drawLine(0, alto/2, ancho, alto/2); //eje x
g.drawLine(0, 0, 0, alto); //eje y

Si se ejecuta el programa así se verán los ejes así:
  

 
Bueno apenas se ve el eje de las Y que esta totalmente a la derecha, pero ahi esta, en el celular por supuesto que se ve mejor, por cierto el emulador que se está usando es el Sony Ericsson K750, cuyo ancho y alto en pixeles es de 176.

Ahora si se desea colocar letreros para denotar los ejes, se usa el método drawString, por ejemplo si se desea agregar el 1 y -1 al eje Y o si se desea agregar los grados al eje X podemos escribir así:

g.drawString("1", 4, 0, Graphics.TOP | Graphics.LEFT);
g.drawString("-1", 3, alto, Graphics.BOTTOM | Graphics.LEFT);
g.drawString("0", 4, alto/2, Graphics.TOP | Graphics.LEFT);
g.drawString("180", ancho/2-5, alto/2, Graphics.TOP | Graphics.LEFT);
g.drawString("360", ancho, alto/2, Graphics.TOP | Graphics.RIGHT);

cuyo resultado sería este:

Datos del eje X
Ahora si, vamos a realizar los cálculos de la función seno, se inicia con el eje x, esté es de lo más simple como se observa en la figura anterior, ya que son los grados que se usarán para la función seno y van desde 0 hasta 360, así que, si han pensado en un ciclo for que recorra desde 0 hasta 360, tienen toda la razón, el código sería el siguiente:

for (i=0; i<=360; i++ ) {

}
Lo que seguiría sería declarar un arreglo de 360 posiciones para que almacene cada uno de los números para posteriormente graficarlos, el arreglo, entonces almacenaría los números 0, 1, 2, 3…. 360, pero justo en este punto se ve un pequeño problema: Yo quiero graficar hasta 360 y el emulador del teléfono celular solo tiene en ancho 176 pixeles como ya lo mencioné, esté es un problema grave, porque un ciclo completo de la función seno va exactamente de 0 a 360 grados, si yo grafico la función está se vería así:


Casi se observa un semi-ciclo de la función, casi se grafica de 0 a 180 grados, esto porque solo se tienen 176 pixeles de ancho en el emulador, ahora si ya se ve el problema ¿verdad? Yo quiero que se grafique todo el ciclo de la función seno, pero no tengo los pixeles suficientes para ello.


La solución es bien simple, se hace un ajuste de lo más sencillo usando la llamada “regla de tres” es decir: “si 360 grados equivalen a 176 pixeles entonces cada grado equivale a X pixeles” al go parecido a esto:
360 -  176
1 grado - x
El resultado para 1 grado queda así:

x = ( 1 * 176) / 360 = 0.488888 pixeles
Entonces cada grado equivale a 0.4888 pixeles, algo que no es del todo practico por que los pixeles son números enteros, aún así esta aproximación es suficiente para mostrar la gráfica de la función seno como se verá un poco más adelante.

Basta con agregar la ecuación anterior al ciclo for mencionado arriba, para obtener en términos de pixeles cada uno de los 360 grados, por otro lado, cada uno de los grados (convertidos ahora en pixeles) se almacenaran en un arreglo de números enteros, entonces la ecuación en términos de las variables que se están manejando para el programa y dentro del ciclo for es la siguiente:

for (i=0; i<=360; i++ ) {
    x[i] = (ancho * i ) / 360; //datos del eje X
}
El arreglo se declara de tipo entero, es llamado “x” y obviamente es de 360 posiciones. Pero vea la ecuación, es una división por lo que, como se vio, genera un número decimal, entonces pareciera que es un error, que se asigne un resultado decimal a un arreglo de enteros, pero no lo es del todo (al menos no en este ejemplo), se aprovecha la propiedad de Java de que, una división de números enteros se puede asignar a una variable de tipo entero perdiendo los decimales, esto debe sonar lógico puesto que lo que se desean son pixeles por que para trazar las líneas que dibujen la función seno se requieren números enteros solamente. Bueno espero me haya explicado.

Datos del eje Y
El eje Y contiene los valores de la función seno, recuerde la ecuación es así:

Y = sin x
Donde “x” son los grados, que en este punto ya están en el arreglo llamado x. Pero veamos que dice la documentación de Java acerca de la función seno (insisto, si no se ve bien da clic en la imagen para verla mejor):

Dos cosas se pueden ver de la documentación, una el ángulo debe estar en radianes y no en grados como se venía manejando y la otra, tanto el ángulo como el resultado deben ser de tipo double.


El primer punto se resuelve fácil convirtiendo cada uno de los 360 grados a radianes, esto se hace fácilmente con la función llamada “toRadians” que está en la clase Math, la función la puedes ver en la documentación de java, no la voy a mostrar pero ahí puedes verla, entonces una sentencia como la siguiente me convierte cada grado en radianes:

angRad = Math.toRadians(i);
Previamente se debe declarar la variable “angRad” de tipo double, con lo anterior se tiene el ángulo listo para la función seno, ahora solo se aplica la función y se asigna a un arreglo para formar los valores para el eje “y”, esto se hace así:

yt[i] = Math.sin(angRad);
El arreglo es llamado “yt” y debe ser declarado de tipo “double” para evitar pérdidas de decimales, y más en este punto puesto que el valor de la función seno es entre 1 y -1. Justo aquí tenemos un nuevo problema, el valor es entre 1 y -1, esto en términos de pixeles es nada, absolutamente nada, pero esto se resuelve bien fácil, una simple multiplicación puede “amplificar” la función de una forma proporcional, por ejemplo si se multiplica la función por 10 así:

yt[i] = 10 * Math.sin(angRad);
entonces “yt” almacenará valores de la función seno, ahora entre 10 y -10, el valor exacto para que la forma de onda se múltiplique y quede proporcionalmente a la pantalla del celular es: alto/2, entonces la ecuación final para “yt” es:

yt[i] = (alto/2) * Math.sin(angRad);
El ciclo for para los dos ejes queda así:

for (i=0; i<=360; i++ ) {
    x[i] = (ancho * i ) / 360; //datos del eje X
    angRad = Math.toRadians(i); //grados a radianes
    yt[i] = (alto/2) * Math.sin(angRad); //datos del eje Y
}
Je je je , no me lo van a creer pero tenemos un nuevo problema, este igual de grave que los otros, con el ciclo anterior tendríamos los valores exactos del eje de las Y ¡¡pero estos valores son negativos¡¡¡ y me servirían a mi para graficar manualmente la función seno, con valores positivos y negativos pero a Java no le sirven por que las coordenadas de la pantalla del celular son positivas siempre. Vaya lio ¿verdad?.

La solución después de analizar un rato el problema es desplazar cada punto del arreglo “yt” cierta cantidad “hacia abajo” (recuerde que las coordenadas de java crecen hacia abajo), para ser exacto se desplaza en pixeles lo equivalente al valor de la variable alto/2, está es la ecuación exacta que me permite hacer lo que menciono:

y[i]=Math.abs(yt[i] - alto/2);
El desplazamiento se hace con una simple resta, la resta genera números negativos, para evitarlo se obtiene el valor absoluto de la resta con lo que se tendría ahora si puros valores positivos y estos valores no me la van a creer pero están ya en coordenadas de Java, listos para su graficación, cada valor se almacena en el arreglo de tipo entero llamado “y”, para este caso se debe agregar un conversor de tipo, puesto que la función del valor absoluto regresa un valor double, el conversor de tipo se agrega entre paréntesis así:

y[i]= (int) Math.abs(yt[i] - alto/2);
el (int) obliga a que el resultado se cambie a entero y se asigne al arreglo de enteros “y”, el código para el ciclo for queda entonces así:

for (i=0; i<=360; i++ ) {
    x[i] = (ancho * i ) / 360; //datos del eje X
    angRad = Math.toRadians(i); //grados a radianes
    yt[i] = (alto/2) * Math.sin(angRad); //datos del eje Y
    y[i]= (int) Math.abs(yt[i] - alto/2);
}
Es posible eliminar el arreglo “yt” del ciclo, y declarar la variable de tipo double, puesto que este arreglo no se va a usar más, así que el código final para el ciclo for (ahora si es el código final se los prometo) queda así:

for (i=0; i<=360; i++ ) {
   x[i] = (ancho * i ) / 360; //datos del eje X
   angRad = Math.toRadians(i); //grados a radianes
   yt = (alto/2) * Math.sin(angRad); //datos del eje Y
   y[i]= (int) Math.abs(yt - alto/2);
}

Graficando la función
Para terminar el post, solo queda graficar los 360 puntos, puesto que ahora si los arreglos “y” y “x” tienen almacenadas las coordenadas y estas cooordenadas ya están en el mundo de java, la grafica se crea trazando pequeñas líneas de una coordenada a otra. Por ejemplo se traza una línea de la coordenada (x[0], y[0]) a la coordenada (x[1], y[1]), la siguiente línea sería de la coordenada (x[1], y[1]) a la coordenada (x[2], y[2]) y así sucesivamente, hasta terminar con la los 360 puntos.

Obviamente esto se realiza con un ciclo for de la siguiente manera:

for (i=0; i<=359; i++ ) {
    g.drawLine(x[i], y [i], x[i+1], y[i+1]);
}

El ciclo va de 0 a 359 ¿Por qué será? Y solo se requirió una simple instrucción que hace uso del método drawLine y listo, el resultado lo puedes ver en la siguiente imagen:

-->

Guau, si quedo bien ¿verdad? Ya para terminar agrego el video tutorial  para este ejemplo, no se muestra la creación de la clase para el Midlet, ni la clase que proviene de la clase Canvas, esto ya ha sido analizado en los post anteriores, por eso ya no lo inclui en el video.


Por si fuera poco anexo el código fuente, es la carpeta completita que genera Netbeans, esta en formato RAR da clic aqui para bajarlo, este realizada con el NetBeans 6.8, si no deseas el código fuente dando clic aqui puedes bajar el archivo JAR para que se lo envies via Bluetooth o USB a tu celualar, si soporta java verás la gráfica del seno sin lugar a dudas, yo lo probe en mi Sony Ericsson W595 y el resultado fue exactamente el mismo que el del emulador.
-->

Clic AQUI para leer más...!

jueves, 7 de enero de 2010

Arreglos



Continuando con la sintaxis de Java Micro Edition, hoy vamos a hablar de una de las estructuras de datos que se usan mucho en programación: los arreglos. Para iniciar nuestro estudio nos remitimos a la WikiPedia, la famosa enciclopedia libre, dando clic aquí puedes entrar al artículo de los arreglos, lo leemos y nos damos una idea de lo que es un arreglo, con esto me evito repetir la definición para que hacerlo si está al alcance de la mano, me interesa más analizar los arreglos pero usando código Java como se ve enseguida.


Arreglos en Java
Es posible crear un arreglo declarando una variable como el siguiente ejemplo:

int A[ ] = new int[10];
El arreglo se llama “A” es de tipo entero y tiene 10 espacios o lugares para almacenar datos, la información que se puede almacenar resulta obvia puros números enteros.

Veamos otro ejemplo, imagine el lector que se desea almacenar la altura, en metros de 20 personas, la opción más sencilla es declarar un arreglo de 20 posiciones y ahí almacenar los datos, que declarar 20 variables para los 20 datos, ahí se ve el uso de los arreglos, la declaración para lo que se pide es así:

float altura[ ] = new float[20];
La variable se llama “altura” y es de tipo float porque una persona puede medir 1.70 metros otra 1.67 y así sucesivamente, como son valores con punto decimal se usa la variable float.

Un ejemplo más imagine que se requiere almacenar el nombre de 40 personas, para realizarlo se declara un arreglo de tipo String así:

String nombres[ ] = new String[40];
Acceso a los datos de un arreglo
El arreglo creado con sentencias como las anteriores, reservan espacio de memoria, por ejemplo el arreglo “A” de enteros visto anteriormente reserva 10 espacios de memoria para almacenar datos, esto se puede imaginar como 10 celdas así:



El arreglo se llama “A” un solo nombre ¿entonces como puedo diferenciar las 10 celdas que hay? Sencillo, usando un número llamado índice, así la primer celda tiene el índice 0 y la última el índice 9, ahora el arreglo lo podemos visualizar como se muestra en la figura:



Escritura de datos en el arreglo
Para escribir datos basta con colocar el nombre del arreglo y entre “[ ]” el número de índice, por ejemplo si deseo almacenar el número 20 en la posición cero escribo así:

A[0] = 20;

Si deseo almacenar el -30 en la posición 8 lo hago así:

A[8] = -30;

Si deseo el número 290 en la celda 3 y el 100 en la 6 lo haría con estas instrucciones:

A[3] = 290;
A[6] = 100;
Con lo anterior puedo visualizar el arreglo así:






Lectura de datos del arreglo
Para leer lo que tiene un arreglo basta con asignarlo a una variable, en este caso la variable debe ser de tipo entero, por ejemplo si se desea saber que dato tiene la celda 6 escribo así:

x = A[6];
Previamente se debió declarar “x” de tipo “int”, después de que se ejecute la instrucción anterior “x” tendrá el valor de 100, ya que ese valor estaba previamente almacenado en el arreglo.

Escritura de datos usando ciclos for

Generalmente la lectura y escritura de un arreglo, por la gran cantidad de datos que hay se realiza con un ciclo for (aunque puede ser cualquier estructura repetitiva, pero el ciclo for se ajusta más)

Por ejemplo si se desea almacenar en el arreglo “A” los primeros 20 números a partir de 0, se podría escribir el código siguiente:

for (i = 0; i<=20; i++) {
  A[ i ] = i;
}

Recuerde en el ciclo for “ i ” toma los valores de 0, 1, 2, 3… 20.

Bueno aquí vamos a dejar esta lección, en la siguiente vamos a usar los arreglos en un ejemplo completo con todo y video-tutorial para que vea el lector donde se puede declarar el código del arreglo.




Clic AQUI para leer más...!

miércoles, 30 de diciembre de 2009

Ejemplo #15 Como agregar imágenes y el comando de salir en el modo gráfico



En el post pasado se vio como se agregan las imágenes en el modo gráfico y por otro lado en el ejemplo #14 “hola mundo en modo gráfico se menciono que el comando “Exit” que se agrega en la clase Canvas, no funciona, se presiona el botón y no pasa absolutamente nada, la razón es bien simple, no hace nada por que no existe ninguna línea de código en el método correspondiente para que realice una acción cuando se presiona el comando, así que el objetivo de este post es aprender a agregar comandos desde la interfaz de bajo nivel, específicamente se muestra como agregar el comando de salir a un MIDlet que muestra una imagen, así que iniciemos.

Cambios al código Midlet
Recuerde que se requieren dos códigos fuente para crear las interfaces de bajo nivel:

• El Midlet
• La clase miCanvas que proviene de la clase Canvas

Ambos códigos ya fueron analizados anteriormente, pero cabe mencionar que en la documentación de la clase MIDlet se indica que si se desea salir del MIDlet para que se liberen los recursos usados en el teléfono celular se debe mandar llamar el método:
destroyAPP() y notifyDestroy(),

estos métodos le "dicen" al celular que el MIDlet se va a destruir para que se liberen los recursos usados, para mandarlos llamar se recomienda la creación de un nuevo método en el código para el MIDlet, un método llamado exitMIDlet así:
public void exitMIDlet() {
   destroyApp(false);
   notifyDestroyed();
}
Al ejecutarse el método se destruye el MIDlet de la memoria del celular completamente, el método se puede agregar en cualquier parte del código de la clase Midlet, más adelante muestro donde podría ir este código.

Otro cambio a la clase MIDlet es el siguiente. Como ya se mencionó en algún post anterior, para mostrar los gráficos se crea un objeto de la clase llamada miCanvas esto se realiza con la instrucción:
helloCanvas = new miCanvas();

Y con esta instrucción se ejecuta el código paint de la clase miCanvas y se muestra en el en la pantalla del celular:
Display.getDisplay(this).setCurrent(helloCanvas);

Con la anterior instrucción se puede decir que “el flujo de programa pasa del MIDlet a la clase miCanvas”, entonces, se tiene un pequeño problema porque si el flujo de programa esta en la clase miCanvas es imposible desde ahí mandar llamar el método exitMiDlet que está en la clase MiDlet. ¿Si me explique? O lo puedo ver con otras palabras: el comando salir se agrega en la clase miCanvas ¿Cómo podría entonces mandar llamar el método exitMIDlet, si este método está en la clase MIDlet? Ahora si se ve el problema ¿verdad?.

La solución es la siguiente, es posible enviar información entre clases, esto solo se logra por medio del constructor de la clase que recibe la información, así pues yo puedo enviar datos de la clase MIDlet a la clase miCanvas por medio del constructor de la clase miCanvas, el constructor se manda llamar cuando se crea el objeto, el objeto se crea en la línea mencionada arriba y que aquí vuelvo a escribir:

helloCanvas = new miCanvas();
Con la línea anterior se crea el objeto, lo que hace esta instrucción realmente es ejecutar el código que viene en el constructor de la clase miCanvas, justo ahí es posible enviarle información a la clase miCanvas, la información se enviá como parámetro entre los paréntesis del constructor.

¿Pero que información voy a enviarle? La respuesta es sencilla, se tiene que enviar un objeto de la clase MIDlet, para que con el objeto se pueda mandar llamar el método exitMIDlet, existe una palabra reservada en J2ME para pasar como parámetro el objeto de la clase actual, esta palabra es simplemente “this”, entonces la sentencia para crear el objeto es así:

helloCanvas = new miCanvas(this);

Se crea el objeto helloCanvas y aparte se envía una referencia al objeto de la clase MIDlet que inicio la ejecución del programa, ups espero haberme explicado.

Finalmente el código completo para la clase MIDlet incluyendo el método exitMIDllet queda así:

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
/**
 * @author User
 */
public class Midlet extends MIDlet {
    miCanvas helloCanvas;
    public void startApp() {
        helloCanvas = new miCanvas(this);
        Display.getDisplay(this).setCurrent(helloCanvas);
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
    }

    public void exitMIDlet() {
        destroyApp(false);
        notifyDestroyed();
    }
}

Cambios a la clase miCanvas
La parte importante del código para esta clase se muestra enseguida (recuerde que este código lo genera NetBeans dar clic aquí si no recuerdas como se hace):

import javax.microedition.lcdui.*;
public class miCanvas extends Canvas implements CommandListener {
    /**
     * constructor
     */
    public miCanvas() {        
        try {
     // Set up this canvas to listen go command events
     setCommandListener(this);
     // Add the Exit command
     addCommand(new Command("Exit", Command.EXIT, 1));
        } catch(Exception e) {
            e.printStackTrace();
        }
    } 
    
    /**
     * Called when action should be handled
     */
    public void commandAction(Command command, Displayable displayable) {        
    }
}

Ahora vea el constructor, esté debe estar preparado para recibir la información que proviene de la clase MIDlet, en este caso lo que se envió fue el mismo Midlet, así que se debe estar preparado para recibirlo, esto lo realizamos agregando una variable entre los paréntesis del constructor así:

public miCanvas(Midlet m ) {        

  // código del constructor
}

Entoces la variable llamada “m” recibe una referencia real del MIDlet, ahora necesito asignarla a una variable para poder usarla por lo que agrego una llamada “mid” así:
Midlet mid;
Ahora simplemente le asigno el valor de “m” así:
mid = m;
El código parcial de la clase helloCanvas queda entonces así:
public class miCanvas extends Canvas implements CommandListener {
    Mildet mid;
 /**
 * constructor
 */
public miCanvas(Midlet m ) {        
     mid = m;
     // código del constructor
 }

Lo único que nos falta es mandar llamar el método para salir del midlet, esto se hace simplemente con la sentencia siguiente:
mid.exitMIDlet();

Esta sentencia se agrega en el método de la clase miCanvas que procesa los comandos y que NetBeans genera automáticamente, justo ahí se coloca la sentencia así:
public void commandAction(Command command, Displayable displayable) {        
  mid.exitMIDlet();
}
Como solo es un comando el que se tiene en el MIDlet es posible hacer lo anterior, cuando hay más de un comando se debe usar un if para identificar cuál comando se presionó pero en este ejemplo solo se tiene el comado de salir.

Bueno otro cambio que se hará es en el código que NetBeans genera para agregar el comando de salir, NetBeans coloca “Exit” nosotros vamos a colocar la palabra “Salir” el código queda así:
addCommand(new Command("Salir", Command.EXIT, 1));

Finalmente agrego el video tutorial, por si quedaron algunas dudas, el programa muestra cómo se agrega una imagen y el comando salir (ahora hice el video con el Sony Vegas y pues no se vio como yo lo deseaba, te recomiendo que lo veas en pantalla completa o desde el sitio de youtube dando clic aqui, mil disculpas)








Clic AQUI para leer más...!

viernes, 25 de diciembre de 2009

Dibujo de imágenes en modo gráfico



La lección de hoy mostrará como cargar una imagen para después desplegarla en la pantalla del celular, en el modo gráfico. Esto es particularmente importante, si en un futuro deseamos realizar animaciones o juegos para el teléfono.

He realizado pruebas en Java Micro Edition y soporta imágenes en los formatos más populares como JPG, PNG y GIF, dando clic aqui puedes ver como crear imágenes en la interfaz de alto nivel algo relativamente fácil, usando las interfaces de bajo nivel no lo es tanto, hay que hacerlo con código, unas pocas líneas se requiere para ello, tampoco nada del otro mundo así que iniciemos, haa se me olvida decir que todo este código debe ir en la clase que hereda de la clase Canvas (donde está el método paint, por si no lo recuerdas).

Paso 1. Declarar un objeto de la clase Image
En J2ME es posible hacer uso de la clase Image para crear objetos que almacenen toda la información de una imagen, para crear el objeto, recuerde que primero hay que declararlo, esto se realiza con la sentencia siguiente:

Image img

El objeto que se declara es llamado img, la sentencia generalmente se coloca justo al principio de la creación de la clase, así:




public class miCanvas extends Canvas implements CommandListener {
    Image img;
    /**
     * constructor
     */
    public miCanvas() {
        try { 
    // etc...

Paso 2. Crear la imagen usando el método createImage
Apenas se declaro el objeto con la sentencia anterior (esto significa que se reserva espacio en la memoria para el objeto img) ahora hay que crearlo realmente, esto se realiza por medio del método creteImage de la clase Image, la sentencia es bien simple como se verá enseguida y debe llevar entre “ “ la ruta de la imagen, así:
img = Image.createImage("/itesiPNG.png");

La imagen se llama itesiPNG y como se puede observar tiene el formato PNG. Por facilidad la imagen fue almacenada previamente en la ruta donde NetBeans crea el código fuente del programa de Java, esto se puede ver en la figura siguiente (recuerda que puedes dar clic en la figura para observarla mejor):


El código anterior generalmente se agrega en el constructor de la clase que hereda de Canvas, aquí lo reproduzco por si no te acuerdas cuál es el constructor:
public miCanvas() {
 try {
    img1 = Image.createImage("/itesiPNG.png"); // Se crea la imagen
   // Set up this canvas to listen tgo command events
    setCommandListener(this);
   // Add the Exit command
    addCommand(new Command("Exit", Command.EXIT, 1));
 } catch(Exception e) {
            e.printStackTrace();
 }
}

El siguiente paso es mostrar la imagen en la pantalla del celular.


Paso #3 Dibujar imagen
Para dibujar la imagen se hace uso del método drawImage, si alguno de ustedes fue curioso y se puso a practicar con la clase Graphics, ahí debió ver este método. El método tal y como lo muestra la documentación de J2ME es así:



La documentación del método indica que debe llevar cuatro párametros entre paréntesis, el primero de ellos es el objeto de la clase Image (en nuestro caso se llama img), el segundo es la coordenada x (por ejemplo 50) el tercero es la coordenada y (por ejemplo 50 también) para finalmente terminar con el parámetro que se llama Anchor o anclaje (por ejemplo Graphics.TOP | Graphics.LEFT), así el ejemplo quedaría:

g.drawImage(img, 50, 50, Graphics.TOP | Graphics.LEFT);

por supuesto que el método debe ser ingresado dentro del método paint() tal y como se observa enseguida:
public void paint(Graphics g) {
   g.setColor(0xFF, 0xFF, 0xFF); // se elige el color blanco de fondo
   g.fillRect(0, 0, getWidth(), getHeight());
   g.drawImage(img1, 50, 50, Graphics.TOP | Graphics.LEFT);    
}

Lo anterior dibuja la imagen a partir de las coordenadas (50, 50), se usa el fillRect para “borrar la pantalla” como se vio en el post pasado.

La figura siguiente muestra como se ve la imagen en el emulador con el código anterior:


Vamos a ver en detalle el último de los parámetros el llamado Anchor Points, para que quede bien claro.

Anchor Points
Voy a trazar un par de líneas que pasen por las coordenada (50, 50), para analizar los llamados Anchor Points (puntos de anclaje), y para ver bien que pasa con la figura voy a pintar el fondo de color amarillo para notar bien su tamaño, entonces voy a ejecutar el código siguiente:
public void paint(Graphics g) {
   g.setColor(0xFF, 0xFF, 0x00); // se elige el color amarillo
   g.fillRect(0, 0, getWidth(), getHeight());
   g.drawImage(img1, 50, 50, Graphics.TOP | Graphics.LEFT);
   g.setColor(0xFF, 0x00, 0x00); // se elige el color rojo para las líneas
   g.drawLine(0, 50, getWidth(), 50);
   g.drawLine(50, 0, 50, getHeight());
}

Que al ejecutarlo resulta:


La coordenada (50, 50) justo es donde se cruzan las líneas, el anchor point que se uso es:

Graphics.TOP | Graphics.LEFT

El anchor Point es el resultado de unir dos parámetros, uno es si la imagen estará arriba o debajo de las coordenadas:

• TOP
• BUTTOM

Y el otro es si está a la izquierda, a la derecha o centrada horizontalmente

• LEFT
• RIGTH
• HCENTER

Esos dos parámetros se unen con el operador lógico “ | ” or.

Pero que más claro que otro ejemplo, vamos a cambiar el Anchor Point ahora por lo contrario que el anterior, “abajo y a la derecha”
Graphics.BUTTOM | Graphics.RIGTH

entonces el código es así:
g.drawImage(img1, 50, 50, Graphics.BUTTOM | Graphics.RIGTH);


El resultado lo puedes ver en la siguiente imagen:




Recuerde que las coordenadas son (50,50) y a partir de ahí se dibuja la imagen dependiendo del punto de anclaje, ahora fue abajo y a la derecha, veamos otro ejemplo:

g.drawImage(img1, 50, 50, Graphics.TOP | Graphics.HCENTER);

da como resultado lo siguiente:


Bueno si lo deseas puedes seguir practicando esto de los Anchor Points yo aquí a cabo este post, por cierto los puntos de anclaje también se usan en el método drawString por si también deseas probarlos ahí.

Haa por cierto, Feliz navidad a todos¡¡¡




Clic AQUI para leer más...!

viernes, 11 de diciembre de 2009

La clase Graphics



Hoy vamos a hablar más acerca de la clase Graphics. Está clase me permite dibujar en pantalla, mostrar incluso imágenes y como se vio en el post anterior es posible mostrar textos. La clase Graphics se crea justo en el método paint() como se vio en la clase HelloCanvas del ejemplo pasado, este método lo reproduzco enseguida:

public void paint(Graphics g) {
 g.drawString("Hola mundo, en modo gráfico",0,0,Graphics.TOP|Graphics.LEFT);
}

Otra vez, la declaración del objeto de la clase Graphics es así:
                                            Graphics  g
Con la declaración anterior, por medio del objeto g, ya puedo usar los métodos de la clase, uno de estos métodos es 

                                           drawString

pero existen muchos métodos más basta con ver la documentación de la clase Graphics, para conocer algunos de sus métodos. La figura siguiente muestra algunos de ellos directamente de la documentación de J2ME (puedes dar clic en la imagen para verla mas grande).



 



Claro que para ver la documentación como se muestra en la imagen se debe tener instalado el SonyEricsson SDK, dando clic aquí   ver el post para su instalación, por si todavía no lo tienes.

 

Método drawLine

 

Como se ve en la figura la clase Graphics tiene infinidad de métodos, ya conocemos uno el drawString, vemos otro:

 drawLine

 

En la documentación dando clic en el método nos lleva a su descripción la cual es mostrada en la siguiente imagen:




La descripción nos dice que el método dibuja una línea entre las coordenadas (x1, y1) y ( x2, y2). Por ejemplo:

                                 drawLine(0, 0, 100, 100);

Dibuja una línea de la coordenada (0,0) a la (100, 100), como se usa el método así:


public void paint(Graphics g) {
   g.drawLine(0, 0, 100, 100);
}

Para usar cualquier método de la clase Graphics, se debe hacer por medio del objeto esa es la razón de que se le agregue la g y el punto y todo lo anterior debe estar dentro del método paint. La figura siguiente muestra la línea en el emulador:



Note como en el emulador no se borran las letras, cuando lo programe físicamente en el celular ahí si se borraba todo y aparecía solo la línea. Más adelante vemos como cambiar eso, para que no aparezcan esas letras.

 

Método setColor

 

En la figura siguiente muestro el método setColor tal y como está en la documentación de J2ME:

 



Este método establece el color en términos de valores RGB (dando clic en el hipervínculo podemos ver la explicación desde la WikiPedia, e incluso se pueden ver los valores para los distintos colores), estos valores son pasados por medio de los parámetros por ejemplo:
.

Negro                         setColor(0, 0, 0)

Blanco                        setColor(255, 255, 255)

 

Este Si se vio el enlace desde la wikipedia está dice qué el color blanco es con el numero FF FF FF, esos valores están en  hexadecimal, según dicen, es mejor manejarlos así, entonces el FF es igual al 255 en decimal. Por cierto si deseo escribirlo en hexadecimal también es posible en java usando el operador 0x, así quedaría el color blanco en hexadecimal

 

                               setColor(0xFF, 0xFF, 0xFF)

 

 Los tres colores básicos se forman así:


Color      en decimal                en hexadecimal                           
Rojo     setColor(255, 0, 0)       setColor(0xFF, 0, 0)
Verde    setColor(0, 255, 0)       setColor(0, 0xFF, 0)  
Azul     setColor(0, 0, 255)       setColor(0, 0, 0xFF)  



Combinando los valores RGB podemos obtener prácticamente cualquier color, la misma wikipedia nos da ejemplos de otros colores por ejemplo:

 

Amarillo                     setColor(0xFF, 0xFF, 0x00)

Purpura                     setColor(0x80, 0x00, 80)

 

Puedes ver más colores desde el artículo de la wikipedia si lo deseas.

 

Como hago uso del método, ya te lo has de imaginar, por ejemplo si deseo crear tres líneas dos horizontales y una vertical, una roja, otra verde y la otra azul, escribo dentro del método paint así:


public void paint(Graphics g) {

     g.setColor(0xFF, 0, 0);  // Se establece el color rojo
     g.drawLine(0, 50, 100, 50); // Se dibuja la primer línea horizontal
     g.setColor(0, 0xFF, 0);  // Se establece el color verde
     g.drawLine(0, 150, 100, 150); // Se dibuja la segunda línea horizontal
     g.setColor(0, 0, 0xFF);  // Se establece el color azul
     g.drawLine(100, 50, 100, 150); // Se dibuja la línea vertical
}
Al ejecutar el código se vería lo siguiente:




Método fillRect

 

La figura siguiente muestra la documentación de este método:




Dibuja un rectángulo relleno con el color actual, a partir de la coordenada (x,y) con un ancho y un alto especificado en los parámetros width y height. Por ejemplo:


public void paint(Graphics g) {
 g.setColor(0xFF, 0, 0);  // Se establece el color rojo
 g.fillRect(45, 60, 100, 100); // rectángulo relleno
}
Al ejecutar el código se muestra la figura siguiente






En este caso dibuja el rectángulo a partir de la coordenada (25, 60) con un ancho de 100 pixeles y con un alto también de 100 pixeles.

 

Ahora te toca a ti, nos llevaría mucho tiempo ver todos y cada uno de los métodos de la clase Graphics, son más de 20, así que no lo voy a hacer, más adelante usare algunos métodos y los explicaré pero hay muchos con los cuales tu puedes practicar, aquí les muestro como se hace, simplemente ver la documentación y a probar como se comporta, así que tu experimenta con los otros métodos.

 

Ancho y Alto de la Pantalla

 

Para finalizar este post, veré dos métodos que me permiten obtener el ancho y alto de la pantalla del celular en el modo gráfico:

 

getWidth(): Obtiene el ancho en pixeles de la pantalla disponible del celular

getheight(): Obtiene el alto en pixeles de la pantalla disponible del celular

 

Estos métodos se heredan a la clase Canvas por eso no tengo que crear ningún objeto, son métodos que puede usar directamente, así por ejemplo si deseo rellenar la pantalla con un color de fondo hago lo siguiente:



public void paint(Graphics g) {
     g.setColor(0xFF, 0, 0);  // Se establece el color rojo
     g.fillRect(0, 0, getWidth(), getHeight);
}

El resultado es el siguiente:




Se acostumbra iniciar el método paint con una llamada a ese par de instrucciones, esto con la finalidad de “borrar” toda la pantalla, se acostumbra el blanco pero puede ser el que cada quien desee.

 

Así por ejemplo si me piden dibujar una línea, un cuadrado sin rellenar, y un cuadrado relleno este sería el código:

 

public void paint(Graphics g) {
      g.setColor(255,255,255); // se establece el color blanco
      g.fillRect (0, 0, getWidth(), getHeight()); // "borra" la pantalla
      g.setColor(10,200,100);
      g.drawLine (0, 0, 100, 100);
      g.drawRect(90, 50, 30, 30);
      g.fillRect (50, 50, 30, 30);
}


Note como ya no se ve ninguna de las letras que aparecía antes, ahora si esta el área de dibujo libre, solo aparece lo que yo mande dibujar.



Clic AQUI para leer más...!

miércoles, 9 de diciembre de 2009

Aplicación de la programación de teléfonos celulares usando J2ME



Ups por fin, terminamos los proyectos finales, ya voy a “postear” más seguido. Hoy les muestro una aplicación practica que se hizo aquí en el ITESI por los alumnos del Grupo de Sistemas Digitales de la carrera de Ingeniería electrónica.

Proyecto: Sistema Electrónico de Identificación por Radio-Frecuencia

Objetivo

Desarrollar un Sistema de hardware y software capaz de identificar y almacenar identificación relevante a la crianza de ganado usando la identificación por radiofrecuencia (RFid). Cabe mencionar que el seguimiento se realiza por un MIDlet programado en un teléfono celular.


La figura siguiente muestra un diagrama a bloques del sistema que se desarrollo.




No voy a entrar en detalle sobre la descripción de cada uno de los bloques, pero el sistema funciona agrandes rasgos así:

1.- Una etiqueta de radiofrecuencia se coloca en el ganado bovino (como si fuera un arete como los que comúnmente se usan) pero la etiqueta tiene un chip especial que contiene un número.

2. Al acercar el lector de RFid, se detecta el número de la etiqueta de RFid que es irrepetible para cada bovino.

3.- El lector de RFid envía el número de etiqueta a la tarjeta DLP-TXRX que se encarga de pasarlo a una PC via puerto USB.

4.- La PC recibe en un programa creado en Java Estándar Edition (J2SE) el número de etiqueta y se lo transfiere (con el mismo programa) a un módulo Bluetooth  conectado al puerto USB de la PC (incluso se hicieron pruebas con PCs que tienen internamente un módulo Bluetooth y el sistema igual funciono muy bien).

5.- El teléfono celular recibe el número de etiqueta vía Bluetooth con un programa creado en Java Micro Edition y registra los datos del bovino.

En el video siguiente se muestran más detalles de los componentes usados y del programa en el celular.




Enseguida se muestran algunas fotos del proyecto.

La figura siguiente muestra la fotografía de las etiquetas de RFid y del lector de RFid, estos fueron adquiridos desde la compañá Parallax



En la figura siguiente se ve el módulo USB que fue comprado a la compañía DLP-Design



Finalmente se ve el programa creado para el celular, obviamente fue programado con Java Micro Edition usando el NetBeans.



En la figura se muestra cuando se inicia la busqueda de dispositivos Bluetooth, esto también fue programado en J2ME.



Aqui muestra la lista de dispositivos Bluetooth encontrados, se elije uno y se conecta para poder recibir el dato de la etiqueta



Enseguida se muestra cuando se detecto la etiqueta y se procede a registrar los datos del bovino.



Bueno aqui dejo este post, solamente fue con fines demostrativos en el siguiente post seguiremos con las lecciones de java.



Clic AQUI para leer más...!

miércoles, 11 de noviembre de 2009

Ejemplo #14 Hola Mundo en modo gráfico



Bueno por fin se va a explicar en este post como se realiza un ejemplo completo usando las interfaces de bajo nivel del celular o también conocido como modo gráfico. Se va a realizar el clásico ejemplo “hola mundo” así que comencemos.

Paso 1. Crear el MIDlet

Este paso ya se analizó, dando clic aquí se puede ver el post, casi al final se indica como crear el MIDlet desde NetBeans, puedes ver el post si no te acuerdas del procedimiento. El resultado de haber realizado este paso es mostrado en la figura siguiente:




Paso #2 Crear la clase que deriva de Canvas
El siguiente paso es crear la clase que hereda de la clase Canvas, este paso también ya se analizo en un post anterior, dando clic aquí puedes acceder a el. También ahí vienen los pasos requeridos para crear la clase llamada HelloCanvas, el resultado de este paso es mostrado en la imagen siguiente:



Paso #3 Agregar el “Hola mundo” a la clase HelloCanvas
El siguiente paso es con la clase HelloCanvas, identificamos el método paint(), y justo en el método drawString, se modifican dos parámetros, uno es el string que se va a dibujar, el “Sample Text” lo modifico por “Hola Mundo, en modo Grafico” y el otro parámetro es el de las coordenadas las que usare son (20, 100) entonces la instrucción queda así:

g.drawString("Hola Mundo en modo Grafico", 50, 100,Graphics.TOP|
Graphics.LEFT);

Paso #4 Crear el objeto de la clase HelloCanvas

Existen dos códigos, dos archivos de java, generados hasta el momento:

• El MIDlet
• La clase HelloCanvas

La pregunta es: ¿como los relaciono? ¿Cómo puedo usar el método paint para que se dibuje el mensaje en la pantalla del celular?, recuerde el celular sigue los métodos que están en el MIDlet, esto significa que el código del MIDlet es el que se ejecuta primero, pero el método de dibujo está en la clase HelloCanvas, si se ve el problema, como puedo desde el MIDlet llamar el método paint.

La solución es sencilla y quizá muchos ya lo saben, recuerde las clases son plantillas para crear objetos, HelloCanvas es una clase, entonces es posible crear un objeto de la clase HelloCanvas y usarlo en la clase MIDlet, déjenme repetirlo, se puede crear un objeto de la clase HelloCanvas y usarlo desde el MIDlet.

Para crear un objeto, primero hay que declararlo, le llamaramos myCanvas, para hacerlo simplemente se coloca el nombre de la clase seguido del nombre del objeto, así:

HelloCanvas miCanvas;

Lo anterior es la declaración, para realmente crearlo se usa el comando new así:
miCanvas = new HelloCanvas();

Después de esa instrucción el objeto llamado miCanvas, está completamente creado y listo para usarse.

Solo falta un detalle, para mostrar cualquier cosa en la pantalla del celular se usa la clase Display, nunca se ha visto en este blog, por que como se recordara NetBenas creaba todo el código incluyendo los objetos de la clase Display, la siguiente instrucción:

Display.getDisplay(this).setCurrent(miCanvas);

Permite dibujar lo que esté en el método paint de la clase Canvas, la clase Display representa el hardware, la pantalla del celular, para acceder a esta pantalla se usa el método getdisplay(this) se usa el this, para indicar que el MIDlet actual es el que se envía como parámetro, finalmente el método setCurrent(HelloCanvas) es usado para indicar que la pantalla actual será la definida por el objeto miCanvas, bueno en resumen el código queda así:

public class Midlet extends MIDlet {
   HelloCanvas miCanvas
   
   public void startApp() {
       miCanvas = new HelloCanvas();
       Display.getDisplay(this).setCurrent(HelloCanvas);
   }
   public void pauseApp() {
   
   }
   public void destroyApp(boolean unconditional) {
   
   }
}

Y listo al ejecutar el código se mostrará en la pantalla el mensaje “hola mundo, en modo gráfico”. Para que quede más claro y lo puedas hacer mucho más fácil se muestra el video tutorial completo para este ejemplo, tal y como se acostumbra en el blog.




En este caso no voy a anexar el código fuente hasta la siguiente entrada, ya que se va a modificar por que el comando exit no funciona como lo puedes ver en el emulador.



Clic AQUI para leer más...!

jueves, 29 de octubre de 2009

La Clase Canvas Parte II



En el post anterior aprendimos a crear una clase que hereda de la clase Canvas, NetBeans crea el código, en este post se va a analizar el código generado. En primer lugar está la definición de la clase la cual ya se hablo mucho en el post anterior, aquí se reproduce:

Public class HelloCanvas extends Canvas implements CommandListener {

     //Aqui va el código generado por NetBeans

}

Esta clase contiene varios métodos generados por NetBeans como ya se mencionó, los cuales se analizan de una forma un tanto superficial porque hay código que no interesa ver en detalle, al menos no ahora pero que NetBeans lo agrega, asi que iniciemos.

Constructor de la Clase HelloCanvas

No se había mencionado nunca en este blog, pero una clase consta de atributos y métodos pero también lleva un método especial llamado constructor.

El nombre del constructor es igual al nombre de la clase, generalmente se usa para inicializar los objetos con valores iníciales, recuerde todo el código analizado en este post, es creado por NetBeans, en el caso del constructor su código generado es el siguiente:



public HelloCanvas() {
  try {
     // Set up this canvas to listen to command events
     setCommandListener(this);
     // Add the Exit command
     addCommand(new Command("Exit", Command.EXIT, 1));
  } catch(Exception e) {
     e.printStackTrace();
  }
 }


Hay mucho código que no es el momento de explicar en detalle todavía, por ejemplo la pareja de instrucciones:


Try {

}
Catch (exeption e) {

}

Sirven para manejar las llamadas excepciones, esto es código que puede lanzar un error en tiempo de ejecución, no nos interesan detalles de esto ahora, recuerde nos interesa realizar el primer ejemplo con interfaces de bajo nivel, así que por lo pronto no diremos más de estas instrucciones

Además el constructor también lleva las siguientes sentencias:

// Set up this canvas to listen to command events
  setCommandListener(this);
// Add the Exit command
  addCommand(new Command("Exit", Command.EXIT, 1));

Con comentarios NetBeans nos explica cada instrucción, en resumen, agrega un exitCommand al Canvas, así al ejecutar el código aparece en la sección de comandos un botón que puede servir para salir de la ejecución, antes no me preocupaba por el código puesto que yo solo arrastraba y soltaba el comando, pero recuerde al usar la clase Canvas hay que hacer todo con código. Entonces el código anterior agrega exitCommand y con la instrucción: setCommandListener deja listo al Canvas para “escuchar” los comandos, en otras palabras para detectar cuando se presiona el exitCommand.

El método paint


Otro método de la clase HelloCanvas es el método paint, se usa para dibujar en el Canvas y mostrarse en la pantalla del celular, en este método se pueden dibujar líneas rectángulos, imágenes etc. pero esto solo se puede hacer por medio de la clase Graphics. Vea el código que genera NetBeans de este método:

public void paint(Graphics g) {
   g.drawString("Sample Text",0,0,Graphics.TOP|Graphics.LEFT);
}


El método lleva entre ( ) lo siguiente:

Graphics g

Esa sentencia crea un objeto de la clase Graphics, el objeto se llama g.

La clase Graphics

La clase Graphics posee todos los métodos necesarios para dibujar en pantalla, mostrar gráficos y mostrar textos. Recuerde, g es el objeto de la clase Graphics, con el objeto creado se pueden usar los métodos de la clase. Por cierto, la clase Graphics tiene muchísimos métodos que me permiten dibujar en el Canvas, como se verá después, por lo pronto entre estos métodos está el método drawString(), que es el que se muestra en el método paint como se ve en la sección anterior.

El método se llama drawString y sirve para dibujar una cadena de caracteres dentro del Canvas, La figura siguiente muestra la descripción de cada parámetro del drawString:






El texto “Sample Text” es el que aparece en la pantalla del celular, después siguen las coordenadas de ubicación del texto que en este caso es (0, 0), después sigue el punto de referencia para situar el texto, en este post no nos interesa ese punto de referencia, luego se discute más a detalle.


Por cierto J2ME divide la pantalla del celular en puntos denominados pixeles el primer punto se ubica en la coordenada (0, 0), la figura siguiente muestra el sistema de coordenadas de Java Micro Edition:





Bueno después de los detalles sigamos con el código que genera NetBeans para la clase HelloCanvas

Métodos para detectar eventos relacionados con las pulsaciones de una tecla

Siguiendo con el código de la clase HelloCanvas se tienen los siguientes métodos en la clase:

protected  void keyPressed(int keyCode) {
}
protected  void keyReleased(int keyCode) {
}
protected  void keyRepeated(int keyCode) {
}


La siguiente tabla describe que hace cada método:

   Método                            Descripción                 
keyPressed()              Se ejecuta cuando se presiona una tecla
keyReleased()             Se ejecuta cuando se suelta una tecla
keyRepeated()             Se ejecuta cuando se deja presionada una tecla

Métodos para detectar eventos relacionados con apuntadores


También la clase Canvas tiene métodos para detectar los eventos relacionados con
apuntadores o mouse estos los genera Netbeans y son:

protected  void pointerDragged(int x, int y) {
}
protected  void pointerPressed(int x, int y) {
}
protected  void pointerReleased(int x, int y) {
}

Cabe aclarar que estos métodos solo son validos en dispositivos que lo soportan, no todos los celulares tienen un apuntador, asi que no se ven más detalles de estos métodos.

Metodo para procesar comandos

El último método de la clase es mostrado en seguida:

public void commandAction(Command command, Displayable displayable) {

}


Cuando se presiona un comando ya sea un okCommnad o un exitCommand se invoca o se ejecuta el método commandAction(), entonces este método me sirve para procesar los comandos.

Bueno ahora si por fin se tienen todos los medios para realizar un ejemplo completo que muestre el mensaje "Hola Mundo" usando Canvas, pero esto lo dejamos para el siguiente post.



Clic AQUI para leer más...!