Home UC3M
Home IT

Desarrollando UI con el API de bajo nivel

 OBJETIVOS


Este API es el favorito de los desarrolladores de juegos porque permite tener control total sobre lo que dibujas en la pantalla, a nivel de pixel, y además puedes definir tus propios eventos de entrada. Lo que se gana en flexibilidad, se pierde en portabilidad ya que el resultado final dependerá del dispositivo concreto en el que se implemente.


 Canvas

La clase Canvas es una subclase de Displayable.

Cuando trabajamos a bajo nivel es importante saber las dimensiones del display, ya que éstas varían de dispositivo a dispositivo y por lo tanto, nuestras apliaciones no deben de asumir un determinado tamaño por defecto. La clase Canvas proporciona los métodos getHeight() y getWidth() para obtener el tamaño del display.

La clase Canvas proporciona un método paint(Graphics g) y varios métodos para la gestión de eventos a bajo nivel que las aplicaciones pueden sobreescribir. La clase Canvas es abstracta y por lo tanto una aplicación debe obligatoriamente extender la clase Canvas para poder utilizarla. La clase que extiende la clase Canvas debe proporcionar obligatoriamente una implementación del método paint()

A continuación se muestra el código de un MIDlet que extiende la clase Canvas (EjemploCanvas.java):

import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;


public class EjemploCanvas extends MIDlet {

    private Display  display;
    private MyCanvas canvas;
   
    public EjemploCanvas(){
        display = Display.getDisplay( this );
        canvas  = new MyCanvas();
    }
   
    protected void startApp(){
        display.setCurrent(canvas);
    }
   
    protected void pauseApp(){
    }
  
    protected void destroyApp( boolean unconditional ){
    }
   
    public void exit(){
        destroyApp( true );
        notifyDestroyed();
    }

    // extiende la clase Canvas
    public class MyCanvas extends Canvas {
    
       public MyCanvas(){
       } 
 
       protected void paint(Graphics g){
         g.setColor( 255, 255, 255 );
         g.fillRect( 0, 0, getWidth(), getHeight() );
         g.setColor( 0, 0, 0 );
         g.drawString( "¡Hola!", getWidth()/2, 0, g.TOP | g.HCENTER );
       }
    }
}


El MIDlet anterior funciona, pero si os fijais para finalizar su ejecución no espera ninguna interacción del usuario. Para ello, vamos a ver ahora como se gestionan los eventos con el API de bajo nivel.

La clase Canvas proporciona algunos métodos para gestionar eventos, que las aplicaciones pueden sobreescribir, estos métodos son:


Por ejemplo, si sobreescribimos el método keyPressed, en MyCanvas:
protected void keyPressed( int keyCode ){
  exit();
}


El resultado será que cuando se presione cualquier tecla, finalizará la aplicación.

Del mismo modo que en el API a alto nivel, se puede definir Commands, que se pueden asociar a un objeto de un clase que extiende la clase Canvas, utilizando el método addCommand.

 Graphics



La clase Graphics es similar a la clase java.awt.Graphics de J2SE, y proporciona métodos para geometría en dos dimensiones. Se definen métodos para dibujar texto, imágenes y líneas, y para dibujar y rellenar rectángulos y arcos, enumero a continuación alguno de ellos:


Si os fijais en los ejemplos anteriores, el método paint de la clase Canvas, acepta como único parámetro un objeto de la clase Graphics.

La clase Graphics también nos da soporte para colores a través de varios métodos:



A continuación, se incluye un MIDlet que dibuja dos líneas (LineTest.java)


import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class LineTest extends MIDlet {
    private Display display;

    public LineTest() {
        display=Display.getDisplay(this);
    }

    public void startApp() throws MIDletStateChangeException {
        display.setCurrent(new LineTestCanvas());
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
    }

    class LineTestCanvas extends Canvas {
        public void paint(Graphics g) {
            // Tamaño del área de dibujo
            int width=this.getWidth();
            int height=this.getHeight();

            // Fondo de la pantalla blanco
            g.setColor(0xFFFFFF);
            g.fillRect(0,0,width,height);

            // Líneas en negro
            g.setColor(0x000000);
            // Dibujamos dos líneas (ejes)
            g.drawLine(0,height,0,0);
            g.drawLine(0,height-1,width,height-1);
        }
    }
}


 Imágenes ARGB


Una de los grandes avances que introduce MIDP 2.0 respecto a la versión 1.0, en lo relacionado con el interfaz de usuario a bajo nivel, es la posibilidad de representar imágenes como arrays de enteros. Esto permite a los MIDlets manipular directamente los datos de una imagen. La idea consiste en representar cada pixel de la imagen como un entero. Esto hace un total de 8 bits por pixel empleados de la siguiente manera:
  • alpha (opacidad): 2 bits
  • Nivel de Rojos: 2 bits
  • Nivel de Verdes: 2 bits
  • Nivel de Azules: 2 bits


Ejemplo:(En notación hexadecimal)
   0xff00ff00 - Verde totalmente opaco

   0x80ff0000 - Rojo semitransparente
La forma en que MIDP 2.0 ofrece la posibilidad de trabajar con imágenes a tan bajo nivel es a través de la implementación de un nuevo método en la clase Graphics, el método drawRGB(int[] rgbData,int offset,int scanlength,int x,int y,int width,int height,boolean processAlpha). Este método dibuja una serie de puntos definidos cada uno de ellos por un entero (que indica su color y su nivel de transparencia) en una zona determinada de la pantalla. Todos los datos necesarios para dicha representación están contenidos en los parámetros que recibe el método:
  • rgbData: array de enteros en el que está contenida la información de todos los puntos a dibujar. Para obtener este array de enteros a partir de una imagen disponemos del método Image.getRGB(int[], int, int, int, int, int, int)
  • offset: indica la posición del array en la que se encuentra el primer valor ARGB.
  • scanlength: offset entre las posiciones de los puntos pertenecientes a dos filas consecutivas en el array rgbData.
  • x: posición horizontal de la zona donde dibujar la imagen.
  • y: posición vertical de la zona donde dibujar la imagen.
  • width: anchura de la zona en la que dibujar
  • height: altura de la zona en la que dibujar.
  • processAlpha: indica si la imagen tiene "canal Alpha" (true) o si por el contrario todos los pixels son totalmente opacos (false).
MIDlet ejemplo: EjemploARGB.java

 ENLACES


API de MIDP/CLDC




inicio | tablón| contacta