Como vimos en el anterior cap�tulo, J2ME se sustenta en dos APIs, por un lado CLDC que hereda algunas de las clases de J2SE, y MIDP que a�ade nuevas clases que nos permitir�n crear interfaces de usuario.
Las clases que nos ofrece CLDC, son las m�s importantes de los siguientes paquetes de J2SE:
java.lang java.util java.io
Adem�s cuenta con el �Generic Conection Framework� que ofrece posibilidades de conexi�n y comunicaci�n.
Por su parte la API MIDP tambi�n hereda de J2SE las clases:
Timer TimerTask
Adem�s MIDP a�ade los siguientes paquetes:
javax.microedition.midlet javax.microedition.lcdui javax.microedition.io javax.microedition.rms
El paquete javax.microedition.midlet, es el m�s importante de todos. S�lo contiene una clase: la clase MIDlet, que nos ofrece un marco de ejecuci�n para nuestras aplicaciones sobre dispositivos m�viles.
El paquete javax.microedition.lcdui nos ofrece una serie de clases e interfaces de utilidad para crear interfaces de usuario. Es algo as� como un peque�o entorno gr�fico similar al AWT, pero, evidentemente, mucho m�s limitado. B�sicamente, nos permite dos tipos de entorno, por un lado podremos trabajar con �Screens� sobre las que podremos colocar elementos de la interfaz de usuario, como textos, menus, etc., por otro, podremos basar nuestras aplicaciones en �Canvas� sobre las que podemos trabajar a nivel gr�fico, es decir, a m�s bajo nivel. Tanto Screen como Canvas son objetos que heredan de la clase �Displayable�.
Todo aquello que puede ser mostrado por la pantalla del dispositivo hereda de forma directa o indirecta de la clase Displayable.
Para el desarrollo de juegos, el objeto Canvas es el que nos va a resultar m�s interesante, y es el que usaremos m�s intensivamente a partir del cap�tulo siguiente.
��C�mo funciona un MIDlet?
Vamos a entrar directamente en materia analizando el programa de ejemplo del cap�tulo anterior.
import javax.microedition.midlet.*; import javax.microedition.lcdui.*;
Con estas dos l�neas importamos las clase MIDlet, que es obligatoria para que nuestro programa se ejecute en el dispositivo m�vil, y tambi�n importamos (con la segunda l�nea) los elementos que vamos a utilizar el la interfaz de usuario.
public class HelloWorld extends MIDlet implements CommandListener { private Command exitCommand; private Display display; private Form screen;
En la primera l�nea declaramos la clase principal del programa, que es p�blica. Hereda de la clase MIDLet e implementa la interfaz CommandListener (en concreto implementaremos el m�todo commandAction()). Tambi�n declaramos una serie de variables que utilizaremos a continuaci�n.
public HelloWorld() { // Obtenemos el objeto Display del midlet. display = Display.getDisplay(this);
Este es el constructor de la clase. Observa que tiene el mismo nombre que la clase (may�sculas y min�sculas incluidas) y adem�s no tiene tipo de retorno, ni siquiera void.
Al ejecutarse un MIDlet, �ste crea un objeto display, que es el encargado de mostrar informaci�n en la pantalla. Para poder utilizarlo, tenemos que obtener una referencia a este objeto. Esto es lo que hace precisamente la siguiente l�nea mediante el m�todo getDisplay() del objeto est�tico Display.
// Creamos el comando Salir. exitCommand = new Command("Salir", Command.EXIT,2);
Un comando es un elemento que nos permite interaccionar con el usuario y le permite introducir comandos. Para crear un comando creamos una instancia (con new) de la clase Command(). Como par�metro le pasamos el texto del comando, el tipo de comando y la prioridad.
Disponemos de los siguientes tipos de comandos:
Comando | Funci�n |
---|---|
OK | Confirma una selecci�n |
CANCEL | Cancela la acci�n actual |
BACK | Traslada al usuario a la pantalla anterior |
STOP | Detiene una operaci�n |
HELP | Muestra una ayuda |
SCREEN | Tipo gen�rico para uso del programador referente a la pantalla actual |
ITEM | Tipo gen�rico para uso del programador referente a un elemento de la pantalla actual |
A veces, y dependiendo del modelo y marca del dispositivo, s�lo se pueden mostrar un n�mero limitado de comandos en la pantalla. Al resto se acceder� mediante un men�.
El tercer par�metro nos permite dar m�s prioridad a unos comandos que a otros a la hora de mostrarlos en la pantalla.
// A�adimos el comando Salir e indicamos que clase lo manejar� screen.addCommand(exitCommand); screen.setCommandListener(this);
Nos resta a�adir el comando (mediante el m�todo addCommand() del objeto screen) a la lista de comandos y establecer que clase permanece a la �escucha� de esos comandos utilizando la clase setCommandListener(). En este caso, el m�todo encargado de procesar los comandos est�n dentro de la propia clase HelloWorld, por lo que utilizamos el operador this. Si quisi�ramos tener una clase separada encargada de procesar los comandos, la indicar�amos aqu�. En concreto, el m�todo que se encarga de procesar los comandos es commandAction(). Para eliminar un comando podemos utilizar removeCommand(Command cmd).
public void commandAction(Command c, Displayable s) { // Salir if (c == exitCommand) { destroyApp(false); notifyDestroyed(); } }
Cuando el usuario genera un comando, se llama al m�todo commandAction(). Este m�todo recibir� dos par�metros. El comando que se gener�, y un objeto de la clase Displayable, que contiene la pantalla del comando.
Cerraremos la aplicaci�n con los m�todos destroyApp() y notifyDestroyed().
// Creamos la pantalla principal (un formulario) screen = new Form("HelloWorld"); // Creamos y a�adimos la cadena de texto a la pantalla StringItem saludo = new StringItem("","Hola Mundo..."); screen.append(saludo);
Dentro de la pantalla podemos situar diversos elementos gr�ficos. Vamos a crear un objeto de tipo Form (formulario) como elemento principal de la pantalla. Veremos dentro de este cap�tulo cu�les son estos elementos.
Seguidamente creamos una cadena de texto (StringItem) y la a�adimos a la pantalla principal mediante el m�todo append().
public void startApp() throws MIDletStateChangeException { // Seleccionamos la pantalla a mostrar display.setCurrent(screen); }
Mediante el m�todo setCurrent() del objeto display (aquel del que obtuvimos la referencia al principio del constructor) seleccionamos la pantalla actual para ser mostrada. Lo hacemos en el m�todo startApp() que es el que se ejecuta en primer lugar.
public void pauseApp() {} public void destroyApp(boolean unconditional) {}
Estas dos l�neas pueden parecer extra�as, ya que son m�todos vac�os (sin c�digo). Como ya vimos, hay que implementar todas las clases heredadas de MIDlet (pauseApp, destroyApp y startApp), por lo que, aunque no contengan c�digo, hay que declararlas.
�Elementos de la interfaz de usuario
Ahora que tenemos una idea b�sica sobre el funcionamiento de un MIDlet, pasaremos a describir los elementos gr�ficos de los que disponemos para crear interfaces de usuario.
Como ya vimos, la clase Screen hereda directamente de Displayable y permite crear las interfaces gr�ficas de alto nivel. Un objeto que herede de la clase Screen ser� capaz de ser mostrado en la pantalla. Disponemos de cuatro clases que heredan de Screen y que nos sirven de base para crear las interfaces de usuario. Son Alert, Form, List y TextBox.
Un MIDlet t�pico estar� compuesto de varios de estos elementos. Por desgracia, y debido al peque�o tama�o de la pantalla, no pueden mostrarse m�s de un elemento a la vez, por lo que tendremos que ir mostrando el elemento que necesitemos que ocupar� toda la pantalla.
Podemos imaginarlo como una serie de fichas de las cuales s�lo podemos mostrar una cada vez.
Para cambiar de una pantalla a otra usamos el m�todo setCurrent de la clase Display (como ya vimos en nuestro ejemplo):
display.setCurrent(list1);
Cada uno de las cuatro clases anteriores dispone de los m�todos (realmente los heredan de Screen):
- String getTitle() - Devuelve el t�tulo de la pantalla
- void setTitle(String s) - Establece el t�tulo de la pantalla
- Ticker getTicker() - Devuelve el ticker de la pantalla
- void setTicker(Ticker ticker) - Establece el ticker de la pantalla
Estos m�todos nos permiten establecer y recoger el T�tulo y el ticker de la pantalla. Un ticker es una l�nea de texto que aparece en la parte superior de la pantalla con un scroll lateral.
�La clase Alert
Permiten mostrar una pantalla de texto durante un tiempo o hasta que se produzca un comando de tipo OK. Se utiliza para mostrar errores u otro tipo de mensajes al usuario.
Para crear una alerta utilizamos su constructor que tiene la siguiente forma:
Alert (String t�tulo, String texto_alerta, Image imagen_alerta, AlertType tipo_alerta)
El t�tulo aparecer� en la parte superior de la pantalla. El texto de alerta contiene el cuerpo del mensaje que queremos mostrar. El siguiente par�metro es una imagen que se mostrar� junto al mensaje. Si no queremos imagen le pasamos null como par�metro. El tipo de alerta puede ser uno de los siguientes:
- ALARM
- CONFIRMATION
- ERROR
- INFO
- WARNING
La diferencia entre uno y otro tipo de alerta es b�sicamente el tipo de sonido o efecto que produce el dispositivo. Vemos un ejemplo:
Alert alerta = new Alert (�Error�,�El dato no es v�lido�, null, AlertType.ERROR);
Y la siguiente l�nea mostrar� la alerta:
display.setCurrent(alerta);
Lo har� durante 1 � 2 segundos. Se puede establecer el tiempo del mensaje con el m�todo
setTimeout(int tiempo)
donde podemos especificar el tiempo en milisegundos. Tambi�n podemos hacer que el mensaje se mantenga hasta que se pulse un bot�n del dispositivo de la siguiente manera:
alerta.setTimeout(Alert.FOREVER);
�La clase List
Mediante la clase List podemos crear listas de elementos seleccionables.
Veamos el constructor:
List (String t�tulo, int tipo_lista, String[] elementos, image[] im�genes)
Los posibles tipos de lista son:
- EXCLUSIVE - S�lo se puede seleccionar un elemento
- IMPLICIT - Se selecciona el elemento que tiene el foco
- MULTIPLE - Permite la selecci�n m�ltiple
Un ejemplo real:
String[] ciudades = {�M�laga�, �Madrid�, �Melilla�}; List lista = new List (�Seleccione una ciudad�, List.EXCLUSIVE, ciudades, null);
En las listas de tipo EXCLUSIVE e IMPLICIT se puede utilizar el m�todo getSelectedIndex() que retorna el �ndice del elemento seleccionado. Pasando como par�metro el �ndice al m�todo getString() nos devuelve el texto del elemento seleccionado. En listas de tipo MULTIPLE podemos utilizar el m�todo:
int getSelectedFlags(boolean[] array_seleccionados)
Esta funci�n rellenar� el array de tipo booleano que le pasamos como par�metro con valores true o false seg�n el elemento correspondiente est� seleccionado. Evidentemente, el array debe tener una correspondencia uno a uno en n�mero de elementos con la lista.
�La clase TextBox
La clase TextBox permite introducir y editar texto a pantalla completa. Es como un peque�o editor de textos.
Veamos el constructor:
TextBox (String t�tulo, String texto, int tama�o_max, int limitaci�n)
Las limitaciones pueden ser alguna de los siguientes:
- ANY - Sin limitaci�n
- EMAILADDR - S�lo una direcci�n de email
- NUMERIC - S�lo se permiten n�meros
- PASSWORD - Los caracteres no ser�n visibles
- PHONENUMBER - S�lo n�meros de telefono
- URL - S�lo direcciones URL
El par�metro tama�o_max indica el m�ximo n�mero de caracteres que se pueden introducir. El par�metro texto es el texto inicial que mostrar� la caja.
TextBox texto = new TextBox (�Mensaje�, ��, 256, TextField.ANY);
Para conocer el texto que contiene la caja puede usarse los m�todos siguientes:
String getString() int getChars (char[] texto)
En el caso de getChars(), el texto ser� almacenado en la variable texto en forma de array de caracteres.
�La clase Form
Un Form es un elemento de tipo contenedor, es decir, es capaz de contener una serie de elementos visuales con los que podemos construir interfaces m�s elaboradas. Los elementos que podemos a�adir a un formulario son:
- StringItem
- ImageItem
- TextField
- DateField
- ChoiceGroup
- Gauge
Como vemos en el diagrama, la clase Form es capaz de manejar objetos derivados de la clase Item. La clase Item representa a un elemento visual que no ocupar� toda la pantalla, sino que formar� parte de la interfaz de usuario junto con otros elementos.
Ya hemos visto un ejemplo de la clase Form en el programa de ejemplo del anterior cap�tulo. En el ejemplo, creamos un elemento de tipo StringItem y lo a�adimos al formulario con el m�todo append().
Los m�todos de la clase Form que nos permiten a�adir, eliminar y modificar elementos del formulario son las siguientes:
int append(Item elemento)
Como ya sabes, append() a�ade al formulario un elemento. Cada vez que a�adimos algo al formulario, a �ste se le asocia un n�mero de �ndice para poder hacer referencia a �l posteriormente. El primer elemento que a�adamos tendr� el valor cero, y as� sucesivamente. Si todo va bien, el m�todo retornar� el �ndice del elemento.
void delete(int �ndice)
El m�todo delete() elimina un elemento del formulario.
void insert(int �ndice, Item elemento)
El m�todo insert() inserta un elemento en la posici�n que indiquemos en el primer par�metro.
Si lo que queremos es sustituir un elemento por otro utilizaremos el m�todo set():
void set(int �ndice, Item elemento)
En alg�n momento es posible que necesitemos conocer el n�mero de elementos del formulario. El m�todo size() nos muestra esta informaci�n:
int size()
Por �ltimo, necesitaremos alg�n mecanismo que nos permitan responder a cambios en los elementos como, por ejemplo, un cambio de valor. El mecanismo es similar al de los comandos que vimos algunas l�neas atr�s. Hemos de implementar la interface ItemStateListener. Concretamente el m�todo siguiente:
void itemStateChanged(Item elemento)
Para indicar al formulario cu�l ser� la clase que responder� a los eventos podemos utilizar:
formulario.setItemStateListener(this);
Si la clase que manejar� los eventos es distinta a la que contiene el formulario sustituiremos el operando this por la clase deseada.
�La clase StringItem
Esta clase ya la conocemos del ejemplo del cap�tulo anterior. Su funci�n es a�adir etiquetas de texto al formulario.
El constructor de la clase StringItem es el siguiente:
StringItem (String etiqueta, String texto)
Si s�lo queremos mostrar un texto, sin etiqueta, paramos una cadena vac�a como primer par�metro (��).
Como vimos antes, s�lo hay que utilizar el m�todo append() de la clase Form para a�adir el texto.
La clase StringItem nos provee adem�s de dos m�todos:
String getText() void setText(String texto)
El primer m�todo devuelve el texto de un StringItem, el segundo, establece el texto que le pasamos como par�metro.
�La clase ImageItem
Con esta clase podemos a�adir elementos gr�ficos a un formulario. El constructor tiene la siguiente forma:
ImageItem (String etiqueta, Image img, int layout, String texto_alternativo)
El par�metro texto_alternativo es un texto que se mostrar� en el caso en el que no sea posible mostrar el gr�fico. El par�metro layout indica c�mo se posicionar� el gr�fico en la pantalla. Sus posibles valores son:
- LAYOUT_DEFAULT
- LAYOUT_LEFT
- LAYOUT_RIGHT
- LAYOUT_CENTER
- LAYOUT_NEWLINE_BEFORE
- LAYOUT_NEWLINE_AFTER
Las cuatro primeras son auto explicativas. LAYOUT_NEWLINE_BEFORE a�ade un salto de l�nea antes de colocar la imagen. LAYOUT_NEWLINE_AFTER hace precisamente lo contrario, primero a�ade la imagen y despu�s un salto de l�nea.
Para cargar una imagen, utilizamos el m�todo createImage() de la clase Image. Veamos un ejemplo:
Image img; try { img = Image.createImage(�/logo.png�); } catch (IOException e) { System.err.println(�Error: � + e); }
A�adir la imagen al formulario es similar a c�mo lo hacemos con un StringItem:
ImageItem img = new ImageItem (��, �/logo.png� ,ImageItem.LAYOUT_DEFAULT, �logotipo�); formulario.append(img);
Hay que tener en cuenta que las im�genes han de almacenarse en el directorio �res� que crea KToolBar, por lo tanto la barra (/) hace referencia a la ra�z de este directorio.
�La clase TextField
La clase TextField es muy similar a la clase TextBox que ya vimos anteriormente. La principal diferencia es que TextField est� dise�ada para integrarse dentro de un formulario en vez de ocupar toda la pantalla.
El constructor de esta clase es similar al de TextBox:
TextField (String etiqueta, String texto, int tama�o_max, int limitaci�n)
Los par�metros tienen el mismo significado que TextBox, exepto el primero, que permite especificar una etiqueta.
�La clase DateField
Con DateField tenemos una herramienta muy intuitiva que permite la entrada de datos de tipo fecha o tipo hora.
DateField (String etiqueta, int modo)
El par�metro modo puede tomar cualquiera de los siguientes valores:
- DATE
- TIME
- DATE_TIME
Para seleccionar la entrada de una fecha o una hora.
DateField fecha=new DateField(�fecha�,DateField.DATE); formulario.append (fecha);
La clase DateField nos provee estos dos m�todos:
Date getDate() void setDate (Date fecha)
El primer m�todo recupera el valor del elemento DateField, y el segundo lo establece.
�La clase ChoiceGroup
Este elemento es similar a la clase List, pero al igual que DateField, puede incluirse en un formulario, de hecho, su constructor es b�sicamente el mismo que el de List:
ChoiceGroup (String etiqueta, int tipo_lista, String[] elementos, image[] im�genes)
Excepto el primer par�metro (que ya conocemos), el resto es exactamente el mismo que el de la clase List.
String[] estados = {"Casado","Soltero","Divorciado","Viudo"}; ChoiceGroup estado = new ChoiceGroup ("Estado", List.EXCLUSIVE, estados, null); screen.append(estado);
�La clase Gauge
La clase Gauge representa un elemento tipo barra de estados que permite indicar un valor gr�ficamente.
El constructor tiene la siguiente forma:
Gauge (String etiqueta, bolean interactivo, int val_max, int val_ini)
Los par�metros val_ini y val_max indican el valor inicial y el valor m�ximo de la barra gr�fica. El par�metro interactivo si est� a true, permitir� al usuario modificar el valor de la barra, si no, s�lo podr� mostrar informaci�n.
La clase Gauge nos ofrece cuatro m�todos muy �tiles:
int getValue() void setValue(int valor) int getMaxValue() void setMaxValue(int valor)
Las dos primeros para establecer y recoger el valor del Gauge, y las otras tienen el cometido de establecer y recoger el valor m�ximo del Gauge.
Gauge estado = new Gauge (�estado�, false, 1, 100); fomulario.append(estado);
El siguiente programa muestra el uso de varios elementos en un formulario a la vez.
import javax.microedition.midlet.*; import javax.microedition.lcdui.*; public class UI extends MIDlet implements CommandListener { private Command exitCommand; private Display display; private Form screen; public UI() { String[] estados = {"Casado","Soltero","Divorciado","Viudo"}; // Obtenemos el objeto Display del midlet. display = Display.getDisplay(this); // Creamos el comando Salir. exitCommand = new Command("Salir", Command.EXIT,2); // Creamos la pantalla principal (un formulario) screen = new Form("Interfaz de usuario"); // Creamos y a�adimos los elemento que vamos a utilizar TextField nombre = new TextField("Nombre","",30,TextField.ANY); DateField fecha_nac = new DateField("Fecha de nacimiento", DateField.DATE); ChoiceGroup estado = new ChoiceGroup("Estado",List.EXCLUSIVE,estados,null); screen.append(nombre); screen.append(fecha_nac); screen.append(estado); // A�adimos el comando Salir e indicamos que clase lo manejar� screen.addCommand(exitCommand); screen.setCommandListener(this); } public void startApp() throws MIDletStateChangeException { // Seleccionamos la pantalla a mostrar display.setCurrent(screen); } public void pauseApp() { } public void destroyApp(boolean incondicional) { } public void commandAction(Command c, Displayable s) { // Salir if (c == exitCommand) { destroyApp(false); notifyDestroyed(); } } }