Heyyyyyyyyyyyyyyy

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

miércoles, 18 de agosto de 2010

Ejemplo #18 “Animación usando GameCanvas: Pelota rebotando”



La animación es un proceso de movimiento de imágenes o dibujos, hoy se muestra un pelotita o bolita o circulo, rebotando por toda la pantalla del celular, esa es la primera animación de varias que se van a realizar. La animación siguiente muestra lo que se pretende hacer con Java en el celular:

>


Como hacer la pelotita
Recuerde que la clase Graphics contiene métodos para dibujar ya se han visto algunas de estos métodos, hay una función que me permite dibujar arcos se llama así

fillArc
Es posible realizar un círculo con esta función, esto se hace así porque la clase Graphics no tienen ninguna instrucción para directamente crear un círculo. La función anterior requiere de 4 parámetros, estos se puede ver en la ayuda de J2ME para la clase Graphics, los parámetros son así:

fillArc(int x, int y, int width, int height, startAngle, arcAngle);

Una imagen vale más que 1000 palabras, así que muestro un par de imágenes con la instrucción fillArc.

Aquí hay otra imagen, que muestra incluso dos líneas para que quede bien claro donde se ubica el circulo cuando se dibuja.
El lector puede seguir experimentando con los parámetros si así lo desea. Note que el primer par de parámetros, que en el ejemplo son (10, 10) ubican la posición de una esquina de un rectángulo imaginario, ese es el punto de referencia para iniciar el dibujo del círculo, después siguen las coordenadas (30, 30) que es el ancho y el alto del circulo, y luego va el ángulo de inicio y el ángulo del arco, para que sea un circulo completo se inicia con el ángulo en 0 y se termina con el ángulo en 360.

Por otro lado, en ese par de imágenes anteriores se puede ver que si la bolita se “desplaza” (primero se puso en la coordenada (0,0) y luego en la (10,10) ), podemos decir que la bolita “se movio”, eso es la animación, sensación de movimiento.

Ciclo para la animación
La animación, se puede resumir en lo siguiente: dibujar la pelota en una posición, borrar la pantalla y volver a dibujarla ahora en otra posición, y repetir todo, una y otra vez, ¿Cómo se hace esto? Bien simple con un ciclo, dando clic aquí para ver el post de los ciclos, si así lo deseas.

Por facilidad se usa el ciclo while(), la condición la colocamos en “true”, con eso basta para lograr un ciclo infinito, después de todo se desea que la pelotita rebote “siempre”, entonces el código para el ciclo es así:


while (true) {
   // código para la animación
}


Pero ¿Dónde va el ciclo? Sencillo, en el método run(), después de todo este ciclo se ejecuta cuando se inicia el subproceso, y como se vio en la entrada anterior aquí es donde van las instrucciones para graficar, así que el método run se va formando así:

public void run() {
   while (true) {
       // Código para la animación
    }
}


El método “sleep” del subproceso

Se mencionó arriba que la animación es simplemente dibujar, borrar, volver a dibujar en otra posición, borrar, y repetirlo, pero necesito hacerlo en pausas, es decir, dibujar por un tiempo (algunos milisegundos), luego borrar todo y volver a dibujar en otra posición después de otro tiempo, esto se puede realizar por medio del subproceso, ya se vio en el post anterior algo de los subprocesos, al crear y después de iniciar el subproceso, se puede hacer uso de sus métodos, hay un método llamado “sleep” (ver la documentación de la clase Thread, si se desean ver más detalles), este método me permite hacer una pausa, un ejemplo en código puede ser el siguiente:

subproceso.sleep(100);

Al ejecutar esa instrucción el programa se detiene durante 100 milisegundos, este método debe ser encerrado en un par de instrucciones así:

try {
  subproceso.sleep(10);
} catch (InterruptedException e) { }


El “try y catch” son requeridos por el programa, si no se agregan hay un error de compilación y nunca podre ejecutar el programa. Esas instrucciones, me permiten capturar algún error, en java se llaman excepciones, ya que el método sleep, puede crear errores por eso se usa el “try” y el “catch”, el código va dentro del ciclo while y va quedando así:


public void run() {
  while (true) {
    // Código para la animación
    try {
      subproceso.sleep(100);
    } catch (InterruptedException e) { }
  }
}

No se profundizará sobre las excepciones quizá más adelante se haga un post de esto, por lo pronto nos interesa la animación, así que continuamos.

Variables usadas en la animación
Se vio en la sección anterior, que la pelotita se “mueve” con solo mover el parámetro x y el parámetro y de fillArc, entonces, como inicio se pueden declarar esos parámetros con una variable para después cambiarlos, así:

int coordX = 0;
int coordY = 0

Recuerde que la declaración va al inicio del método, ya con las variables declaradas, se puede crear el circulo con la instrucción fillArc, en este caso es un circulo con 20 pixeles de ancho y alto, esta es la instrucción

g.fillArc(coordX, coordY, 20, 20, 0, 360)

La instrucción va dentro del ciclo, el código toma la forma siguiente:

public void run() {
  int coordX = 0;
  int coordY = 0
  while (true) {
     g.fillArc(coordX, coordY, 20, 20, 0, 360)   

     try {
       subproceso.sleep(100);
    } catch (InterruptedException e) { }

  }
}

¿Ahora que se necesitará para mover la pelotitia? Simplemente desplazar las coordenadas, estas que son variables se pueden desplazar sumandoles un valor, así:
coordX = coordX + 1
coordY = coordY + 1

Otro ejemplo sería así:

coordX = coordX + 5
coordY = coordY + 5

O uno con desplazamientos diferentes,

coordX = coordX + 5
coordY = coordY + 3

Vea los ejemplos, en el primero solo se desplaza la pelotita 1 pixel, el segundo 5 pixeles ¿Qué diferencia hay? Entre 1 pixel o 5 pixeles en el desplazamiento, la animación siguiente nos da la respuesta:

>

Nota: La animación es para fines ilustrativos solamente, está realizada con un programa llamado SwishMax 2, por lo que no se si vaya más rápido o más lento cuando se programe en Java.

Obviamente la pelotita va más rápido con 5 pixeles que con 1, por que los incrementos en las coordenadas son mayores, podemos entonces decir que el sumarle una variable a la coordenada hace que se cambie su velocidad, por comodidad se va a almacenar este desplazamiento en variables también, se declaran así:

int velX = 5;
int velY = 5;


Yo las inicie en 5, el lector puede hacerlo en 1 o en otro valor, queda el código así:
public void run() {
   int coordX = 0;
   int coordY = 0;
   int velX = 5;
   int velY = 5;
 

   while (true) {
     g.fillArc(coordX, coordY, 20, 20, 0, 360)
     try {
       subproceso.sleep(100);
     } catch (InterruptedException e) { }
     coordX = coordX + velX;
     coordY = coordY + velY;
   }
}

Es obvio también, que si se ejecuta este código la pelotita se va de largo ¿Por qué? Ya se imaginará el lector que falta agregar un código que haga que la pelotita rebote esto es que cambie de dirección como se ve en la figura:


Aparte, en la figura se observa donde está el punto (0,0) en el sistema de coordenadas de Java para que el lector lo recuerde, también se muestra el alto y ancho de la pantalla, que es donde la pelotita rebota, entonces bastaría con que yo compare la posición de la pelotita para saber si llego a lo alto de la pantalla (o a lo ancho) y simplemente cambio de dirección.

Entonces, una simple comparación puede detectar si la pelotita llego a lo alto del panel, primero pues vamos a usar un par de variables para obtener el alto y ancho del panel así:

int ancho = getWidth();
int alto = getHeight();

Ahora sí, se inician las comparaciones, que tal un if para “ver “ si ya toco el alto así:

if (coordY > alto) {
  // código para cambiar de dirección
}

Pero vea la figura y recuerde lo que se menciono arriba, el círculo se dibuja tomando como referencia la esquina de un rectángulo, que justo son las coordenadas x e y:



¿Cómo se cambia la dirección?

La respuesta es bien simple, para el ejemplo que se muestra, la pelotita se desplaza hacia abajo por que se suma se suma la velocidad (variable velY) pero que tal si envés de sumar se resta la velocidad, la pelotita se iría hacia arriba.

Entonces para que la pelotita cambie la dirección basta con restar la velocidad, esto se hace simplemente con cambiar el signo de la variable así:

velY = -velY;

Con esa instrucción la pelotita rebotará al llegar a lo alto de la pantalla, el código del método run queda de la siguiente forma al agregar el primer if:

public void run() {
 int coordX = 0;
 int coordY = 0;
 int velX = 5;
 int velY = 5;
 while (true) {
   g.fillArc(coordX, coordY, 20, 20, 0, 360)
   try {
     subproceso.sleep(100);
   } catch (InterruptedException e) { }
   coordX = coordX + velX;
   coordY = coordY + velY;
   if ((coordY + 20) > alto) {
     velY = -velY;
   }
 

 }
}
Ahora vea en la figura el siguiente caso que tiene que ver con la coordenada Y todavía:

La pelotita se dirige a la coordenada 0, de Y, para ese momento la velocidad es negativa obviamente deseamos que rebote de ahí, entonces se requiere otra comparación para hacerlo, así:

if (coordY < 0) {
   velY = -velY;
}
Con eso basta para que detecte el límite de la pantalla y al cambiar de signo la velocidad, la pelotita cambia de dirección.

Es posible unir los dos if’s para la coordenada Y usando el operador OR (operador lógico) de Java, el operador OR en Java es así || el código queda entonces con un solo if de esta forma:

if ((coordY + 20) > alto || (coordY < 0 ))
  velY = -velY;
También quitamos las { }, puesto que sigue solo una instrucción no son necesarias.

Todo lo que se hizo para la coordenada Y se aplica para la coordenada X y el ancho de la pantalla , así que les dejo como va quedando el código para el método run ya con los if’s para las ambas coordenadas

public void run() {
  int coordX =0, coordY=50;
  int velX = 5;
  int velY = 5;
  int ancho = getWidth();
  int alto = getHeight();
  while(true) {
    g.fillArc(coordX,coordY,20,20,0,360);
    try {
      subproceso.sleep(30);
    } catch (InterruptedException e) { }
    coordX = coordX + velX;
    coordY = coordY + velY;
    if ((coordX + 20) > ancho || (coordX < 0) )

       velX = -velX;
    if ((coordY + 20) > alto || (coordY < 0 ))
       velY = -velY; 

    flushGraphics();
  }
}

También en el código anterior se agrego  el método flushGraphics al final del código.

Recuerde la animación es un ciclo de dibujar, borrar, dibujar en otra posición, borrar…. Y así sucesivamente, para terminar falta el borrado el código anterior, no funcionaría como se desea si no es borrada la pantalla, esto se hace colocando el fondo del color que se quiera, en este caso es en color negro, aparte se agrega el código para pintar la pelotita en color azul.

g.setColor(0x000000); //color negro
g.fillRect(0, 0, ancho, alto);
g.setColor(0x0000FF); //color azul


Por fin se muestra el código completo para el método run(), el código para borrar se coloca después del while

public void run() {
  int coordX =0, coordY=50;
  int velX = 5;
  int velY = 5;
  int ancho = getWidth();
  int alto = getHeight();
  while(true) {
    g.setColor(0x000000); //color negro
    g.fillRect(0, 0, ancho, alto);
    g.setColor(0x0000FF); //color azul
   

    g.fillArc(coordX,coordY,20,20,0,360);
    try {
      subproceso.sleep(30);
    } catch (InterruptedException e) { }
    coordX = coordX + velX;
    coordY = coordY + velY;
    if ((coordX + 20) > ancho || (coordX < 0 )

      velX = -velX;
    if ((coordY + 20) > alto || (coordY < 0 ))
      velY = -velY;
    flushGraphics();
  }
}

Vaya este post se me hizo larguísimo, pero ya es todo, fiel a mi costumbre se muestra el video-tutorial completito para que no haya errores de ningún tipo y el lector pueda implementarlo con toda la confianza del mundo.
 




Clic AQUI para leer más...!

sábado, 7 de agosto de 2010

Ejemplo #17 “Hola mundo usando la clase GameCanvas”



Ya se vieron a lo largo del blog, varios video tutoriales donde se muestra como se usa la clase Canvas para dibujar elementos gráficos, incluso en el último ejemplo se gráfica la función seno en el celular, ahora veremos una clase que nos permitirá realizar animaciones fácilmente, se mostrará el ejemplo más sencillo que puede haber para esta clase, el clásico mensaje “Hola Mundo”, así que iniciemos.

La Clase GameCanvas

En este post se muestra la clase GameCanvas diseñada para simplificar el desarrollo de juegos para el teléfono celular. Con esta clase es muy fácil detectar las teclas que son presionadas por el usuario además fácilmente se actualiza la pantalla, sin necesidad de usar la técnica llamada doble buffer, la cual tampoco veremos aquí pues ya no se necesita, además esta clase está optimizada precisamente para la programación de juegos, esté ejemplo y los siguientes mostrarán ejemplos sencillos de su uso.

Se presenta detalladamente las partes de la clase y como se va codificando, quizá sea repetitivo al volver escribir a cada rato la clase, pero me gusta hacerlo así, creo que así queda más claro.

Siguiendo el mismo procedimiento que los ejemplos de la clase Canvas, se crea primero una clase que derive o herede de la clase GameCanvas, en código es así:

public class EjemploGameCanvas extends GameCanvas {
// Código de la clase
}

El nombre de la clase es EjemploGameCanvas, recuerda que en Java para definir la herencia se usa la palabra extends, entonces la clase EjemploGameCanvas hereda todos los métodos y atributos de la clase GameCanvas, por cierto a su vez la clase GameCanvas deriva de la clase Canvas.

Por otro lado la pura definición como está arriba nos marcaría error, puesto que hay que importar el paquete de clases donde se ubica la clase GameCanvas, la instrucción Import lo hace, se codifica como se muestra enseguida y se coloca al iniciar la clase:

import javax.microedition.lcdui.game.*;

Pero eso no es todo, está clase porque así está diseñada, se debe ejecutar en su propio “subproceso”, para implementar esto en Java se usa la interfaz Runnable, para hacerlo se escribe en la definición de la clase el “implements Runnable” así:

import javax.microedition.lcdui.game.*;
public class EjemploGameCanvas extends GameCanvas implements Runnable {
    // Código de la clase
}

Veamos una explicación muy superficial de los subprocesos.

Subprocesos

Para ver el concepto de subproceso se debe pensar en, por ejemplo, el procesador de textos Word, donde precisamente estoy escribiendo este texto, el Word fue programado para que haga varias tareas digamos “al mismo tiempo”, por ejemplo mientras se escribe el texto, Word crea un subproceso para verificar la ortografía la cuál señala con una línea roja, entonces Word se dice que es multitarea, esto es, la realización aparente de poder hacer varias tareas “al mismo tiempo”, aunque esto no es verdad puesto que las computadoras solo tienen un único procesador, pero como estos ejecutan millones de instrucciones por segundo nos dan la ilusión de que lo hace en paralelo

Para dar esta ilusión de ejecutar las instrucciones en paralelo en Java, se usan los subprocesos, en nuestro caso se usan en clase Game Canvas, porque esta clase debe aislarse del resto del código, además así se diseño esta clase, para facilitarnos la vida a la hora de programar animaciones y juegos, por eso se agrega a la definición de la clase el “implements Runnable” ese es el primer paso para crear el subproceso, pero todavía faltan más cosas.

Constructor de la clase

Por otro lado, olvidándonos un momentito de los subprocesos, recuerde algo, todas las clases deben llevar su constructor (método que se llama igual que la clase) y que generalmente sirve para inicializar variables que se usaran a lo largo del programa.

El constructor de la clase que hereda de GameCanvas, según la documentación, requiere un parámetro que es de tipo booleano (verdadero o falso), si es verdadero se suprimen los mecanismos para los eventos de las teclas, si es falso se activan los mecanismos y se pueden detectar fácilmente las teclas que se han presionado, esto se verá después por lo pronto nosotros le vamos agregar al constructor el parámetro “true” puesto que solo se mostrará un mensaje en la pantalla, entonces el constructor para la clase que acabamos de crear es así:

public class EjemploGameCanvas extends GameCanvas implements Runnable {
    public EjemploGameCanvas () {
      super(true); // código del constructor
    }
}
Vea la instrucción

super(true)

Justo ahí se le envía el valor de verdadero (true), la instrucción “super” significa que se manda llamar el constructor de la superclase, recuerde la herencia, Canvas es la superclase de GameCanvas, esté es un requisito para usar la clase GameCanvas, si no se llama el constructor de la superclase simplemente nos marca un error de compilación.

El método run

Regresando a los subprocesos, toda clase que lleve en su definición el “implements Runnable” debe a fuerzas implementar el método run() este método es la clave de los subprocesos, cuando se activa el subproceso, este método es el que se ejecuta, la clase ahora agregando el método run toma la forma siguiente:

public class EjemploGameCanvas extends GameCanvas implements Runnable {
   public EjemploGameCanvas () {
      super(true); // código del constructor
   }
   public void run() {
     //Código del subproceso
   }
}
El Método getGraphics()

Por otro lado, la clase GameCanvas contiene varios métodos, uno de ellos es getGraphics(), este método es el primer paso para iniciar a dibujar en el GameCanvas, el método regresa un objeto tipo grafico con el que posteriormente se dibuja, la instrucción para usarlo es así:

g = getGraphics();

g es el objeto gráfico, pero recuerde, en Java todo se debe declarar antes de usar, para declarar un objeto es bien simple, inicia con el nombre de la clase (en este caso Graphics), seguido por el nombre que yo desee (yo quiero la “g”) la declaración queda así :

Graphics g;

¿Donde va este código?, la declaración la colocamos después de la definición de la clase, y la llamada al método en el constructor que es el método que se ejecuta primero, así se prepara todo para iniciar el dibujo en el GameCanvas, queda entonces la clase así:



public class EjemploGameCanvas extends GameCanvas implements Runnable {
  Graphics g;
  public EjemploGameCanvas () {
  super(true); // código del constructor
    g = getGraphics();
  }
  public void run() {
    //Código para el subproceso
  }
}


Creación del Subproceso

Otra vez regresamos a los subprocesos, no basta con escribir el “implements Runnable” y el método “run” se debe en verdad crear el subproceso, esto se hace creando un objeto de la clase Thread, como se crea el objeto, ya lo vimos, primero se declara y se crea usando la palabra new, esto incluso se puede escribir en una sola línea así:

Thread subproceso = new Thread(this);

O como el objeto g, en dos líneas, con la excepción de que g no requiere la palabra new.

Ya está creado el subproceso con la línea anterior pero mientras no se inicie jamás se va a ejecutar el método run, así que para iniciarlo basta con mandar llamar su método start así:

subproceso.start();

¿Dónde va el código? Nos conviene que se inicie inmediatamente, después de todo nuestro primer ejemplo solo mostrará “hola mundo en la pantalla” y ya, así que de nueva cuenta el constructor es buena idea para este código, queda entonces la clase así:

public class EjemploGameCanvas extends GameCanvas implements Runnable {
  Graphics g;
  public EjemploGameCanvas () {
     super(true); // código del constructor
     g = getGraphics();
     Thread subproceso = new Thread(this);
     subproceso.start();
  }
  public void run() {
   //Código
  }
}

Ahora si a Dibujar

Listo tenemos todos los elementos para empezar a dibujar lo que querramos en la pantalla del celular, usando de por medio el objeto “g” tal y como se hizo con la clase Canvas, esto ya se vio por lo que no entrare en detalles, el código siguiente coloca la pantalla del celular en negro y escribe “hola Mundo usando GameCanvas”, en color magenta creo.

// pantalla en negro
g.setColor(0x000000);
g.fillRect(0, 0, getWidth(), getHeight());
// dibujo de las letras “hola mundo…
g.setColor(0xff00FF);
g.drawString("Hola mundo, con GameCanvas", 0, 60, Graphics.LEFT | Graphics.TOP);

¿Dónde va el código? En el método run() después de todo es el que se ejecuta al iniciar el subproceso, antes de ver donde, veamos otro método de la clase GameCanvas.

El método flushGraphics();

Este método, también de la clase GameCanvas es usado para colocar realmente en la pantalla del celular lo dibujado por el objeto “g”, el código anterior que pinta la pantalla de negro y dibuja el letrero esta en la memoria o como le llaman en el “buffer” y no se puede ver, hasta que se invoque el método flushGraphics(), al hacerlo se ve ahora si lo dibujado, este código va al final, despueés del método drawString, también va en el método run, queda finalmente el código así:

public class EjemploGameCanvas extends GameCanvas implements Runnable {
  Graphics g;
  public EjemploGameCanvas () {
    super(true); // código del constructor
    g = getGraphics();
    Thread subproceso = new Thread(this);
    subproceso.start();
  }
  public void run() {
    // pantalla en negro
    g.setColor(0x000000);
    g.fillRect(0, 0, getWidth(), getHeight());
    // dibujo de las letras “hola mundo…
    g.setColor(0xff00FF);
    g.drawString("Hola mundo, con GameCanvas", 0, 60, Graphics.LEFT |   Graphics.TOP);
   flushGraphics();
  }
}

Video

Enseguida se muestra el video para este ejemplo, recuerde que se requiere el MIDlet principal para mandar llamar la clase que hereda de GameCanvas esto ya se vio en un post anterior, por eso no lo repito aquí, aún así el tutorial muestra todo el procedimiento, todo él código para agregar la clase creada al MIDlet.




Clic AQUI para leer más...!

miércoles, 21 de julio de 2010

Como obtener la nueva versión del SDK de Sony Ericsson



Vaya después de tanto tiempo --la última entrada del blog data del 13 de enero de 2010 :D -- ya estoy de regreso… después de más de 6 meses vuelvo a retomar el blog… ahora si tengo todas las intenciones de “postear” más seguido.

Bueno ahora si hablemos de lo que nos corresponde, hoy se muestra como obtener la nueva versión del SDK de sony Ericsson (ya se explico una vez qué es y cómo obtenerlo en la entrada del blog con fecha de martes 19 de mayo de 2009 y que si lo deseas puedes ver dando clic aquí), pero a más de un año de esa fecha las cosas cambian, ya no son las instrucciones indicadas ahí, las que nos llevan al SDK de Sony Ericsson, ya cambio la página Web así que reiniciamos el blog justo como lo empezamos con las nuevas versiones del software, además muchos lectores me dicen que por que a ellos no les aparecen los emuladores de Sony, pues aqui se dice como obtenerlos.


¿Por qué usar el SDK de Sony Ericsson?

La respuesta es de lo más simple y sencilla, la razón, es porque mi teléfono celular es un Sony Ericsson W550, esa es la respuesta. Habrá más de algún lector que tenga su celular de Nokia o de Motorola bueno pues a ellos les conviene bajar el SDK para sus teléfonos que también existe solo es cuestión de buscarlo, así le pueden sacar el máximo provecho a su teléfono incluso quizá hasta el software tenga un emulador exactamente igual al de su celular.

Primer paso

Todo Inicia desde la página para desarrolladores de Sony Ericsson cuya dirección es la siguiente:


Al dar clic en la dirección se observa la nueva versión de la pagina web de Sony, donde se da clic en el menú “technology” tal y como se observa en la figura


Al hacerlo se despliega todas las diferentes tecnologías con las que cuentan los celulares de Sony Ericsson, obviamente ahí esta Java, se da clic en la sección de Java, para ser exacto en “Read More” tal y como se observa en la figura.
Al hacer lo anterior, parece la opción donde se indica, que es el SDK y cuestiones por el estilo, casi hasta abajo viene el link para bajar el SDK cuya versión esta desde octubre de 2009, la figura siguiente indica el link para bajar el SDK.




Al dar clic en el link aparece por fin el archivo de instalación del SDK

Y listo se baja el archivo para instalar, está en formato ZIP, se des-comprime y se da doble clic en el archivo de instalación

Antes de instalar la nueva versión se debe desinstalar la versión anterior del SDK

Cuando intente instalar la nueva versión del SDK se marca un error que dice: “One of the applications you are trying… bueno mejor vean el error en la imagen siguiente:


En la documentación que se incluye en el archivo ZIP (archivo llamado “README”) se indica que hay que desinstalar las versiones anteriores, así que intento hacerlo y me sale el mismo error al desinstalar el SDK¡ y aquí se los muestro en esta imagen

Siguiendo las instrucciones del archivo “README”, ahi se indica que se debe detener el “SDK Service” si deseamos desinstalar el software, esto es sencillo, simplemente se da clic en “Stop SEMC SDK Service” en el menú de instalación del SDK, bueno una imagen vale más que mil palabras


Al hacer clic sale una ventana de MS-Dos donde se detiene el servicio del SDK después de esto, se inicia la desinstalación del programa, ya sea desde el mismo menú en la opción (Unistall) o desde el panel de control, se desinstala sin dificultad alguna el SDK, incluso la siguiente figura muestra la ventana inicial de la desinstalación:


Finalmente se instala la nueva versión del Sony Ericsson SDK, dando doble clic al archivo que previamente se des-comprimió y listo.

Adjuntar la nueva versión del SDK con el NetBeans

Ahora para poder usar esta versión recién instalada se adjunta al NetBeans, existe un video en una entrada anterior que hace justamente eso, aquí lo reproduzco para que se vea como se hace es lo mismo para esta nueva versión.

Actualizar los proyectos de NetBeans a la nueva versión del SDK

Al realizar lo anterior me encontré que muchos de mis proyectos en el NetBeans estaban marcados en color rojo como se observa:


Esto debido a que se realizaron con la otra versión del SDK basta con dar clic derecho en el proyecto deseado y elegir “Properties” y en el menú “platform” se elige la nueva versión y listo una figura quizá ayude un poco más a visualizar lo que se dijo:





 Bueno con esto se termina esta entrada, hasta la próxima que esperemos sea muy pronto.

Clic AQUI para leer más...!

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...!