API de alto nivel para Interfaz de usuario (javax.microedition.lcdui.Screen) 

F. Javier García Castellano
Web: http://decsai.ugr.es/~fjgc, Mail: fjgc@decsai.ugr.es
IndiceInicioPerl

(C) Decsai
Web: http://decsai.ugr.es

4.- API de alto nivel (clase Screen)

Como hemos visto Screen es la clase base para utilizar el API de alto nivel del interfaz de usuario. Podemos agrupar las subclases Screen en dos tipos: un primer tipo encapsula completamente los ítems del interfaz de usuario siguiendo una estructura predefinida, dentro de este tipo tenemos List, TextBox y Alert, este tipo no permite que se añadan o quiten otro tipo de componentes. En el segundo tipo tenemos la clase Form que permite a las aplicaciones añadir o quitar ítems de la pantalla, tal y como desee el programador del Midlet, no obstante, la clase Form no permite encapsular completamente sus componentes como las clases del otro tipo de Screen.

La clase Screen sólo proporciona cuatro métodos, cuya funcionalidad puede ser utilizada por sus clases hijas. Estos cuatro métodos nos permitirán poner y ver el título de la aplicación (setTitle() y getTitle()) y para poner y ver el ticker de la aplicación (setTicker() y getTicker()):

void setTitle(String s);
String getTitle();

void setTicker(Ticker ticker);
Ticker getTicker():

El Ticker es una línea de texto en movimiento que aparece en la pantalla, además del título. Se configura con la clase Ticker.

Describamos brevemente las clases que heredan den Screen:

Modifica el anterior ejemplo de Hola Mundo con el API de alto nivel, para que muestre el Ticker.

4.1.- Gestión de Comandos en el API de alto nivel

Como vimos la clase Displayable define los métodos addCommand(Command cmd), removeCommand(Command cmd) y setCommandListener(CommandListener l) que heredan todas sus subclases y que nos va a permitir que el usuario interactúe con el Midlet. Dichos comandos se implementan con la clase Command.

La clase Command tiene el siguiente constructor:

public Command(String label, int commandType, int priority);

Este constructor crea un nuevo comando cuya etiqueta viene dada por el primer parámetro. El segundo nos dará el tipo de comando que es y, finalmente, el tercer parámetro nos da la prioridad del comando. La prioridad del comando determinará como se muestra el comando al usuario, una valor bajo (0 es la máxima prioridad) significa que se le dará un lugar con mayor visibilidad y habrá más posibilidad de asignarle una tecla (los teléfonos móviles no suelen tener muchas teclas).

Los tipos de comandos que existen son los siguientes:

Para añadir o borrar un comando al objeto Displayable que estemos usando se hace con los métodos:

public void addCommand(Command cmd);
public void removeCommand(Command cmd);

por ejemplo:

 Command exitcmd = new Command ("Salir", Command.EXIT,0);
 form1.addCommand(exitcmd)

Una vez que el comando ha sido creado y añadido a la pantalla, este es visible para el usuario. Para poder tratar estos comandos cuando son invocados tendremos que implementar el interfaz CommandListener con el Displayable al que se ha añadido el comando. Una vez que se ha configurado el CommandListener se añade a la clase Displayable.

CommandListener es un interfaz que tiene un sólo método:

public void commandAction(Command c, Displayable d);

En este método será donde tratemos el comando, los parámetros son pues el comando que ha introducido el usuario y el Displayable donde se ha producido. Para añadir el Listener simplemente usamos el método:

public void setCommandListener(CommandListener l)

Resumiendo, para poder crear un comando y poder tratarlo, tendremos que crear un objeto Command y añadirlo a nuestro Displayable. Posteriormente tenemos que tener una clase (por ejemplo, nuestro propio midlet) que implemente el interfaz CommandListener, finalmente añadimos el CommandListener a nuestro Displayable.

Por ejemplo para añadir el comando Exit a nuestro Midlet, se haría como sigue:

  ....
  public class MiMidlet extends Midlet implements CommandListener  {
  
  private static final Command EXIT_COMMAND= new Command ("Salir", 
                                                           Command.EXIT, 0);
  private static final TextBox textbox= new TextBox("Pruebas",
                                                    "Mete tu texto aquí",
                                                    100, TextField.ANY);

  ....
       textBox.addComand(EXIT_COMMAND);
       textBox.setCommandListener(this);
  ....
  public void commandAction(command c, Displayable d){
         if (c == EXIT_COMMAND) {
            destroyApp(true);
            notifyDestroyed();
         } else {
            System.out.println("Otro comando pulsado");
         }
   }
  ....

4.2.- Clases Form e Item

Form como hemos visto es un contenedor de ítems del interfaz gráfico, todos los ítems que se pueden añadir a Form descienden de la clase Item, la cual contiene las subclases:

La clase Form tiene dos constructores:

public Form (string Titulo);
public Form (string Titulo, Item[] items);

El primero crea un Form vacío con sólo el título. El segundo sirve para inicializar el Form con una array de ítems. El orden de los ítems en el array determinará como se van a colocar en el Form.

En MIDP 1.0 la clase Form no permite un control del layout, de forma que no podemos controlar la forma en que se colocan los componentes, aunque esto ha cambiado en MIDP 2.0. No obstante, si hacemos nuestro Midlet basándonos en MIDP 1.0, hay unas cuantas reglas para determinar como se sitúan los ítems en la clase Form:

Para añadir ítems al Form tenemos 3 métodos append:

public void append (Item item);
public void append (Image imagen);
public void append (String string);

El primer método añade una clase Item al Form, el segundo y el tercer son una forma rápida de añadir una imagen o una cadena. En el Form tenemos una lista interna donde se van almacenando cada ítem que vamos añadiendo, de esta forma, cada ítem del Form puede ser accedido mediante un índice que indica la posición en esa lista, el primer ÍTem, tendrá índice igual a cero.

Para eliminar un Item de un Form podemos usar el siguiente método:

public void delete (int index);

Para insertar un Item en un lugar concreto del Form podemos usar el siguiente método

public void insert (int index, Item item);

Para modificar un Item del Form disponemos del siguiente método:

public void set (int index, Item item);

Para obtener un determinado Item de un Form podemos usar el método:

public Item get (int index);

Finalmente si queremos ver el número de ítems que contiene un Form, tenemos el método:

public int  size();

Veamos un ejemplo donde creamos un Form con sólo una cadena y botón para salirnos de la aplicación

Ejemplo2.java Ejemplo de Form y Command.

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

public class Ejemplo2 extends MIDlet implements CommandListener {
    private Display display;
    private Form form;
    private Command salir; 

    //Constructor
    public Ejemplo2(  ) {

	//Cogemos el display
	display=Display.getDisplay(this);

        //Creamos el form 
        form = new Form ("Ejemplo 2");
        form.append("Hola Mundo\n");

	//Creamos el comando de salir
	salir=new Command("Salir",Command.EXIT, 3);

        //anadimos el comando al form y activamos el oyente
	form.addCommand(salir);
        form.setCommandListener(this);
    }
 
    //Metodo que se llama cuando pasamos de Pausado a Activo
    protected void startApp(  ) {
        display.setCurrent(form);
    }
 
    //Metodo que se llama cuando pasamos de Activo a Pausado
    protected void pauseApp(  ) {
    }
 
    //Metodo que se llama cuando se destruye el midlet
    protected void destroyApp(boolean incondicional) {
    }

    //Metodo para el tratamiento de datos de teclado 
    public void commandAction(Command c, Displayable d) {
	//Miramos si nos salimos o mostramos la alerta
	if (c ==salir) {
	   destroyApp(true);
	   notifyDestroyed();
        } else System.out.println("Otro comando pulsado");
        
   } 
}

Modifica el anterior ejemplo para que añada dos cadenas. También debe añadir un comando que cambie la segunda cadena por la primera.

4.3.- Subclases de Item

Item es la superclase usada por todos los componentes que pueden formar parte de un Form. Todos los ítem tiene un campo label(etiqueta), que es una cadena que va con el ítem. Esta etiqueta se mostrará cerca del componente cuando se muestra dicho ítem por pantalla. Para ver y poner esta etiqueta tenemos dos métodos:

public void setLabel(String label)
public String getLabel()

El primer método da un valor a la etiqueta del ÍTem, si es null, entonces el ítem no tiene etiqueta. El segundo método devuelve la etiqueta de un ítem.

La clase Item es una clase abstracta por lo que tiene que ser instanciada por otras clases, aunque el apartado 4.2, dimos un avance de las clases que heredan de ítem, veámoslas con más detenimiento.

4.3.1.- Clase StringItem

Esta clase nos permite mostrar una cadena (String) en un objeto Form. Tengamos en cuenta que como esta clase hereda de Item tendrá asociado una etiqueta (label) además de la cadena propiamente dicha, la cadena de esta clase se puede proporcionar en el constructor:

public StringItem(String label, String texto);

El texto de una clase StringItem puede ser leído o modificado con los siguientes métodos:

public String getText();
public void setText(String texto);

Téngase en cuenta que la etiqueta y el texto de la clase StringItem, normalmente, no se mostrarán de igual forma. Por lo que no es una clase para escribir dos cadenas, como puede pensarse.

Veamos un ejemplo donde creamos un Form con dos StringItem, un botón para salirnos de la aplicación y otro para cambiar un StringItem

Ejemplo3.java Ejemplo de StringItem

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

public class Ejemplo3 extends MIDlet implements CommandListener  {
 
    private Display display; //Pantalla del dispositivo
    private Form form;       //form que vamos a presentar
    private Command salir;   //comando para salirnos
    private Command cambiar; //comando para cambiar de estado
    private StringItem salida; //cadena de salida
    private int cuenta;

    //Constructor
    public Ejemplo3( ) {
      cuenta=0;

      //Cogemos el display
      display=Display.getDisplay(this);

      //Creamos el form 
      form = new Form ("Ejemplo 3");
      form.append("Ejemplos de StringItem\n");

      //Creamos un nuevo StringItem
      salida=new StringItem("CADENA:", "Contador ="+cuenta);
      //lo añadimos al form
      form.append(salida);

      //Creamos el comando de salir
      salir=new Command("Salir",Command.EXIT, 3);
      //Creamos el comando de cambiar
      cambiar=new Command("Cambiar",Command.SCREEN, 1);

      //anadimos los comandos al form y activamos el oyente
      form.addCommand(salir);
      form.addCommand(cambiar);
      form.setCommandListener(this);
    }//Fin constructor

 
    //Metodo que se llama cuando pasamos de Pausado a Activo
    protected void startApp(  ) {
	System.out.println("Midlet Activo\n");
        display.setCurrent(form);
    }//fin método startApp
 

    //Metodo que se llama cuando pasamos de Activo a Pausado
    protected void pauseApp(  ) {
	System.out.println("Midlet Pausado\n");
    }//fin metodo pauseApp
    

    //Metodo que se llama cuando se destruye el midlet
    protected void destroyApp(boolean incondicional) {
	System.out.println("Fin del Midlet\n");
    }//fin metodo destroyApp


    //Metodo para el tratamiento de datos de teclado 
    public void commandAction(Command c, Displayable d) {
	//Miramos si nos salimos o mostramos la alerta
	if (c ==salir) {
	    destroyApp(true);
	    notifyDestroyed();

	//Cambiamos la cadena de salida del form	    
	} else if (c == cambiar) {
	    cuenta++;
	    salida.setText("Contador ="+cuenta);
        } else System.out.println("Otro comando pulsado");
    }//fin del metodo commandAction
}

Modifica el ejemplo anterior para que muestre o no, dependiendo de un comando, el label.

4.3.2.- Clase ImageItem

Esta clase es similar a StringItem, pero está pensada para colocar una imagen en lugar de texto. Para la imagen se utiliza una clase Imagen que se verá con más profundidad cuando veamos el API de bajo nivel. La clase ImageItem tiene un sólo constructor:

public ImageItem(String label, Image imagen, int layout, String altText);

En este constructor además de la imagen propiamente dicha, se añade una etiqueta a la imagen, un layout que nos indica la política a seguir a la hora de colocar la imagen y finalmente un cadena para poner en lugar de la imagen, si por alguna razón (que se exceda del tamaño de la pantalla, dice el estándar MIDP) no se pudiera poner la imagen.

El parámetro layout nos va a indicar la forma de colocar la imagen en la pantalla, es una máscara de bits (bitmask) que se realiza a partir de combinaciones permitidas de:

Hay que tener en cuenta que LAYOUT_RIGHT, LAYOUT_LEFT y LAYOUT_CENTER son mutuamente exclusivas.

Veamos un ejemplo de utilización de un ImageItem usando la imagen logo.png (en el directorio de aplicaciones se tiene que meter en el directorio res):

Ejemplo4.java Ejemplo de ImageItem

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


public class Ejemplo4 extends MIDlet implements CommandListener {
    private Display display;
    private Alert alerta;

    private Form form;
    private ImageItem imagen;

    private Command salir; 

    //Constructor
    public Ejemplo4(  ) {

	//Cogemos el display
	display=Display.getDisplay(this);

        //Creamos el form y le anadimos el item
        form = new Form ("Ejemplo 4");

	try {
	    //Creamos el item del Form
	    imagen= new ImageItem("", Image.createImage("/logo.png"), ImageItem.LAYOUT_CENTER, "Logo de Java");
	    
	    form.append(imagen); 
	} catch (java.io.IOException e) {
	    form.append(" Ha habido un problema al leer el fichero logo.gif\nMotivo:"+e); 
	}

	//Creamos el comando del form
	salir=new Command("Salir",Command.EXIT, 3);

        //anadimos el comando al form y activamos el oyente
	form.addCommand(salir);
        form.setCommandListener(this);
    }
 
    //Metodo que se llama cuando pasamos de Pausado a Activo
    protected void startApp(  ) {
        display.setCurrent(form);
    }
 
    //Metodo que se llama cuando pasamos de Activo a Pausado
    protected void pauseApp(  ) {
    }
 
    //Metodo que se llama cuando se destruye el midlet
    protected void destroyApp(boolean incondicional) {
    }

    //Metodo para el tratamiento de datos de teclado 
    public void commandAction(Command c, Displayable d) {
	//Miramos si nos salimos o mostramos la alerta
	if (c ==salir) {
	   destroyApp(true);
	   notifyDestroyed();
        } else System.out.println("Otro comando pulsado");
        
   } 

}
4.3.3.- Clase TextField

Nos permite editar un campo de texto (normalmente de una línea) dentro de un Form. El constructor para esta clase es:

public TextField(String label, String texto, int maxSize, int constraints);

El primer parámetro indica la etiqueta, el segundo el texto con el que puede estar inicializado el TextField, el tercer nos indica en número máximo de carácteres que admite y el tercero son las restricciones del campo de texto. Las restricciones (constraints) nos especifican el tipo de dato que se puede introducir en el TextField, y son las siguientes:

Para acceder o modificar las restricciones podemos utilizar los siguientes métodos:

public int getConstraints()
public void setConstraints(int constraints)

Para leer o modificar el texto del TextField tenemos los siguientes métodos:

public void setString(String text)
public String getString()
public int getChars(char[] data)

Con el primer método asignamos un String al texto del TextField, con el segundo método podemos coger el texto en un objeto String y con el tercer método recogemos también el texto, pero lo que hace es guardarlo como un array de carácteres que se le pasa como argumento, devolviendo el número de carácteres leídos. Téngase en cuenta que si al llamar a getChars() el array que se pasa como parámetro es demasiado pequeño se producirá un error.

Con las siguientes funciones podremos leer y modificar el número de carácteres máximos que admite nuestro TextField:

public int getMaxSize()
public void setMaxSize(int maxSize)

Mientras que con la función size() podremos saber el número de carácteres que hay escritos.

La clase TextField nos va a permitir realizar una serie cambios dentro del texto que se puede editar, siempre que sean consistentes con las restricciones y para ello tenemos los siguientes métodos:

public void delete(int offset, int length);

La anterior función elimina length carácteres empezando desde el carácter offset.

public void insert(char []chars, int offset, int length, int position);

La anterior función inserta carácteres del array chars desde chars[offset] hasta chars[offset+length-1] en la posición position del TextField .

public void insert(String src, int position);

La anterior función inserta la cadena src en la posición position del TextField .

public void setChars(char []chars, int offset, int length);

La anterior función reemplaza el contenido del TextField con chars[offset] hasta chars[offset+length-1] del array de carácteres.

public int getCaretPosition();

La anterior función nos devuelve la posición del caret dentro del TextField . Se denomina caret al punto de inserción donde se encuentra el cursor dentro el TextField.

Haz un ejemplo donde se pida login y password, los compare con valores almacenados y en un StringItem diga sin son correctos o no.

4.3.4.- Clase DateField

Esta clase nos permite introducir fechas y horas. Su constructor es como sigue:

public DateField(String label, int mode);

El primer parámetro del constructor nos indica la etiqueta de la clase y el segundo indica el modo de funcionar del ítem y toma los siguientes valores:

Esta clase también nos va a permitir ver y cambiar el modo de funcionar con los métodos:

public int getMode()
public void setMode(int mode)

Además podemos leer y cambiar los valores de DateField con:

public Date getDate()
public void setDate(Date date)

Obsérvese que los anteriores métodos utilizan un objeto del tipo Date para leer o modificar, respectivamente, el DateField.

Veamos un ejemplo de utilización de un DateField y de un TextField:

Ejemplo5.java Ejemplo de DateField y de un TextField.

import java.util.Date;
import java.util.Calendar;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;


public class Ejemplo5 extends MIDlet implements CommandListener {
    private Display display;
    private Alert alerta;

    private Form form;
    private TextField nombre;
    private DateField fecha; 
    private StringItem cadena; 

    private Command continuar; 
    private Command salir; 

    //Constructor
    public Ejemplo5(  ) {

	//Cogemos el display
	display=Display.getDisplay(this);

        //Creamos los items Form
 	  //un item para preguntar el nombre
          nombre= new TextField("Nombre:","",10,TextField.ANY);
   	  //un item para preguntar la fecha de nacimiento
          fecha= new DateField("Fecha Nacimiento:",DateField.DATE);
	  //una cadena
	  cadena= new StringItem("","");
  

        //Creamos el form y le anadimos los items
        form = new Form ("Ejemplo 5");
        form.append(nombre); 
        form.append(fecha);
        form.append(cadena);

	//Creamos los comandos del form
	continuar=new Command("Continuar",Command.OK, 0);
	salir=new Command("Salir",Command.EXIT, 3);

        //anadimos los comandos al form y activamos el oyente
	form.addCommand(continuar);
	form.addCommand(salir);
        form.setCommandListener(this);
    }
 
    //Metodo que se llama cuando pasamos de Pausado a Activo
    protected void startApp(  ) {
        display.setCurrent(form);
    }
 
    //Metodo que se llama cuando pasamos de Activo a Pausado
    protected void pauseApp(  ) {
    }
 
    //Metodo que se llama cuando se destruye el midlet
    protected void destroyApp(boolean incondicional) {
    }

    //Metodo para el tratamiento de datos de teclado 
    public void commandAction(Command c, Displayable d) {
	//Miramos si nos salimos o mostramos la alerta
	if (c ==salir) {
	   destroyApp(true);
	   notifyDestroyed();
        } else if (c == continuar) {
	    
	    //usamos calendar para ver la diferencia con la hora actual
	    Calendar cal1=Calendar.getInstance();
	    Calendar cal2=Calendar.getInstance();
	    Date date=fecha.getDate();
	    if ((date==null) || (nombre.getString().equals(""))) {
		cadena.setText("¡Antes de darle a Continuar mete tus datos!");
		return;
	    }
	    cal2.setTime(date);

	    int edad=cal1.get(Calendar.YEAR)-cal2.get(Calendar.YEAR);
	    
	    //Quitamos la entrada de datos
	    form.delete(0);
	    form.delete(0);
	    //Quitamos el comando de continuar
	    form.removeCommand(continuar);
	    //Cambiamos la cadena por un mensaje con la edad
	    cadena.setText("Hola "+nombre.getString()+"\n Tu edad es (más o menos)="+edad+" años");
        } else System.out.println("Otro comando pulsado");
        
   } 

}
4.3.5.- Clase ChoiceGroup

Esta clase nos muestra una lista de elementos donde podremos elegir uno o varios de estos elementos. Los constructores de esta clase son:

public ChoiceGroup(String label, int choiceType)
public ChoiceGroup(String label, int choiceType, String[] stringElements, Image[] imageElements)

En el primer constructor tenemos la etiqueta del ítem y el tipo de lista. En el segundo constructor tenemos además un array con los elementos de esa lista y con imágenes asociadas a estos elementos de la lista. El segundo parámetros de ambos constructores es, como hemos dicho, el tipo de lista y puede tomar los siguientes valores:

Con las métodos insert() y append() podremos insertar o añadir elementos a la lista. Con las funciones delete() o deleteAll() podremos borrar elementos de la lista, mientras que con set() podremos modificar un elemento y con size() obtendremos el número de elementos de la lista.

public int append(String stringPart, Image imagePart)
public void insert(int elementNum, String stringPart, Image imagePart);
í
public void delete(int elementNum);
public void deleteAll();

public void set(int elementNum, String stringPart, Image imagePart);
public int size();

Podemos obtener/poner el elemento seleccionado (si usamos un modo EXCLUSIVE) o un vector de booleanos (si usamos MULTIPLE) con los siguientes métodos:

EXCLUSIVA
public int getSelectedIndex();
public void setSelectedIndex(int elementNum, boolean selected):

MULTIPLE
public int getSelectedFlags(boolean[] selectedArray_return);
public void setSelectedFlags(booleaín[] selectedArray);

También tenemos métodos para obtener el texto o la imagen de un elemento de la lista, o simplemente ver si está seleccionado.

public String getString(int elementNum);
public Image getImage(int elementNum);
public boolean isSelected(int elementNum);

Veamos un ejemplo de utilización de dos ChoiceGroup, uno exclusivo y el otro múltiple:

Ejemplo6.java Ejemplo de ChoiceGroup

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


public class Ejemplo6 extends MIDlet implements CommandListener {
    private Display display;
    private Alert alerta;

    private Form form;
    private TextField nombre;
    private ChoiceGroup sexo; 
    private ChoiceGroup aficiones; 

    private Command salir; 

    //Constructor
    public Ejemplo6(  ) {

	//Cogemos el display
	display=Display.getDisplay(this);

        //Creamos los items Form
 	  //un item para preguntar el nombre
          nombre= new TextField("Nombre:","",10,TextField.ANY);
   	  //un item para preguntar el sexo
          sexo= new ChoiceGroup("Sexo:",ChoiceGroup.EXCLUSIVE);
	  sexo.append("Hombre",null);
	  sexo.append("Mujer",null);
   	  //un item para preguntar por las aficiones
          aficiones= new ChoiceGroup("Aficiones:",ChoiceGroup.MULTIPLE);
	  aficiones.append("Lectura",null);
	  aficiones.append("Cine",null);
	  aficiones.append("Deportes",null);
	  aficiones.append("Amigos",null);
	  aficiones.append("Television",null);
	  aficiones.append("Otras",null);

        //Creamos el form y le amadimos los items
        form = new Form ("Ejemplo 6");
        form.append(nombre); 
        form.append(sexo);
        form.append(aficiones);

	//Creamos el comando del form
	salir=new Command("Salir",Command.EXIT, 3);

        //anadimos el comando al form y activamos el oyente
	form.addCommand(salir);
        form.setCommandListener(this);
    }
 
    //Metodo que se llama cuando pasamos de Pausado a Activo
    protected void startApp(  ) {
        display.setCurrent(form);
    }
 
    //Metodo que se llama cuando pasamos de Activo a Pausado
    protected void pauseApp(  ) {
    }
 
    //Metodo que se llama cuando se destruye el midlet
    protected void destroyApp(boolean incondicional) {
    }

    //Metodo para el tratamiento de datos de teclado 
    public void commandAction(Command c, Displayable d) {
	//Miramos si nos salimos o mostramos la alerta
	if (c ==salir) {
	   destroyApp(true);
	   notifyDestroyed();
        } else System.out.println("Otro comando pulsado");
        
   } 

}
4.3.6.- Clase Gauge

Esta clase nos va a permitir tener una barra gráfica que puede ser usada para visualizar un valor dentro de un rango o para que sea introducido por el usuario. Un objeto de este tipo tiene un rango con un valor mínimo (el 0), un valor máximo y el valor actual. Este ítem puede permitir ser modificado por el usuario (interactivo) o no y mostrar simplemente una barra (como una barra de progreso). Para crear un ítem de este tipo tenemos el constructor:

public Gauge(String label, boolean interactive, int maxValue, int initialValue);

Los parámetros que recibe el constructor del ítem Gauge, van a ser un etiqueta, un valor lógico indicando si va a ser interactivo o no, el valor máximo que alcanza (el mínimo es cero) y un valor inicial.

Para poder trabajar con este ítem tenemos dos métodos con los que podremos leer y modificar el valor actual, esto métodos son:

public int getValue();
public void setValue(int value);

También nos va a permitir obtener el valor máximo que puede alcanzar y modificarlo. Además de ver si es interactivo o no con los siguientes métodos:

public void setMaxValue(int maxValue);
public int getMaxValue();
public boolean isInteractive();

Veamos un ejemplo de utilización de un Gauge interactivo:

Ejemplo7.java Ejemplo de Gauge

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


public class Ejemplo7 extends MIDlet implements CommandListener {
    private Display display;
    private Alert alerta;

    private Form form;
    private Gauge sonido;

    private Command salir; 

    //Constructor
    public Ejemplo7(  ) {

	//Cogemos el display
	display=Display.getDisplay(this);

        //Creamos el item del Form
        sonido= new Gauge("Volumen",true,10,5);

        //Creamos el form y le amadimos el item
        form = new Form ("Ejemplo 7");
        form.append(sonido); 

	//Creamos el comando del form
	salir=new Command("Salir",Command.EXIT, 3);

        //anadimos el comando al form y activamos el oyente
	form.addCommand(salir);
        form.setCommandListener(this);
    }
 
    //Metodo que se llama cuando pasamos de Pausado a Activo
    protected void startApp(  ) {
        display.setCurrent(form);
    }
 
    //Metodo que se llama cuando pasamos de Activo a Pausado
    protected void pauseApp(  ) {
    }
 
    //Metodo que se llama cuando se destruye el midlet
    protected void destroyApp(boolean incondicional) {
    }

    //Metodo para el tratamiento de datos de teclado 
    public void commandAction(Command c, Displayable d) {
	//Miramos si nos salimos o mostramos la alerta
	if (c ==salir) {
	   destroyApp(true);
	   notifyDestroyed();
        } else System.out.println("Otro comando pulsado");
        
   } 

}
4.3.7.- Tratamiento de cambios de estados de los Item

Un aspecto a tener en cuenta en el uso de Form es la detección de cambios en los ítems que lo componen. Cambios en el estado de los ítems son notificados a un ItemStateListener registrado con el Form. Un ItemStateListener es un interfaz con un sólo método: itemStateChanged() que es llamado cuando cualquier item del Form tiene un cambio:

public void itemStateChanged (Item item);
í

Para poder tratar los cambios en los ÍTem, nuestro Midlet debe de implementar el interfaz ItemStateListener e implementar el método itemStateChanged(), al igual que pasaba con en la gestión de comandos con el interfaz CommandListener y el método commandAction. Una vez hecho esto tenemos que registrar nuestro Midlet como Listener usando el método setItemListener() de la clase Form (al igual que hacíamos con setCommandListener en la gestión de comandos):

public void setItemStateListener (ItemStatesListener l);

por ejemplo:

form.setItemStateListener (this);
í

Modifica el ejemplo del Gauge para que cada vez que cambie el Gauge, en una cadena se muestre el valor que tiene.

4.4.- La clase Alert

La clase Alert hereda de la clase Screen y nos sirve para mostrar un mensaje (y opcionalmente una imagen) al usuario. Es como un pop-up o un MessageDialog. Al igual que la clase Form los cambios se reflejan autom´ticamente en pantalla (siempre que el Midlet esté Activo). Los constructores de la clase Alert son:

public Alert(String title);
public Alert(String title, String alertText, Image alertImage, AlertType alertType);

El primer parámetro title(en ambos constructores) es el título de la alerta que aparece en la parte superior de la misma, mientras que alertText, ya en el segundo constructor, es el texto que muestra. Con el tercer parámetro alertImage se puede especificar una imagen o null, si no queremos poner ninguna. El último parámetro indica el tipo de alerta, que es un objeto de la clase AlertType y que puede ser:

El tipo de alerta se especifica en un objeto AlertType mediante el método void setType(AlertType tipo). Con la clase AlertType también podemos reproducir sonidos, si el dispositivo está capacitado para ello, para ello se usa el método boolean playSound(Display display); que tiene asociado cada tipo de alerta, como podemos ver en el siguiente ejemplo:

AlertType.Error.playSound(display);
í

Por defecto el tiempo que permanece un Alert en pantalla está determinado por el dispositivo o puede ser cambiado usando el método setTimeout() que especifica el tiempo en milisegundos (o usando la constante Alert.FOREVER), también se puede ver el tiempo de vida que tiene con getTimeout():

public void setTimeout(int time);
public int getTimeout();

Para mostrar la alerta al usuario, se la tenemos que pasar a la instancia de Display que tiene nuestro Midlet como cualquier otro objeto Displayable:

display.setCurrent(alert);

También tenemos métodos para acceder y cambiar las distintas carácterísticas de nuestra clase Alert:

public int getDefaultTimeout()

public AlertType getType()
public void setType(AlertType type)

public String getString()
public void setString(String str)

public Image getImage()
public void setImage(Image img)

Veamos un ejemplo donde se van a poder parametrizar desde el Midlet el Alert a usar, y donde también ser verá como tratar los cambios de los estados en los Item de un Form:

Ejemplo9.java Ejemplo de Alert

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


public class Ejemplo9 extends MIDlet implements CommandListener, ItemStateListener  {
    private Display display;
    private Alert alerta;

    private Form form;
    private TextField titulo;
    private TextField texto; 
    private ChoiceGroup tipo;
    private ChoiceGroup tiempo;
    private Gauge segundos;
    

    private Command continuar; 
    private Command salir; 

    private int segant=2;
 
    //Constructor
    public Ejemplo9(  ) {

	//Cogemos el display
	display=Display.getDisplay(this);

        //Creamos los items Form
 	  //un item para preguntar el titulo del alert
          titulo= new TextField("Titulo","Alerta",10,TextField.ANY);
   	  //un &item para preguntar el texto del alert
          texto= new TextField("","Este es el texto del Alert",100,TextField.ANY);

   	  //un item para preguntar que tipo del grupo se escoger para el alert
	  tipo=new ChoiceGroup("Tipo",ChoiceGroup.EXCLUSIVE);
          tipo.append("Alarm",null);
          tipo.append("Confirmation",null);
          tipo.append("Error",null);
          tipo.append("Info",null);
          tipo.append("Warning",null);
	  tipo.setSelectedIndex(0,true);

   	  //un item para preguntar que tiempo escoge para el alert
	  tiempo=new ChoiceGroup("Tiempo",ChoiceGroup.EXCLUSIVE);
	  tiempo.append("Siempre",null);
	  tiempo.append("Un rato",null);
	  tiempo.setSelectedIndex(0,true);

   	  //un item para preguntar que tiempo en segundos escoge para el alert
	  segundos=new Gauge("Segundos (0=Siempre) (Max=20seg=",true, 20, segant);

        //Creamos el form y le anadimos los items
        form = new Form ("Ejemplo Alert");
        form.append(titulo); 
        form.append(texto);
        form.append("\n");
        form.append(tipo);
        form.append("\n");
        form.append(tiempo);
        form.append(segundos);

	//Creamos los comandos del form
	continuar=new Command("Continuar",Command.OK, 0);
	salir=new Command("Salir",Command.EXIT, 3);

        //anadimos los comandos al form y activamos el oyente
	form.addCommand(continuar);
	form.addCommand(salir);
        form.setCommandListener(this);
        form.setItemStateListener(this);
    }
 
    //Metodo que se llama cuando pasamos de Pausado a Activo
    protected void startApp(  ) {
	System.out.println("Paso a estado Activo");
        display.setCurrent(form);
    }
 
    //Metodo que se llama cuando pasamos de Activo a Pausado
    protected void pauseApp(  ) {
	System.out.println("Paso a estado Pausado");
    }
 
    //Metodo que se llama cuando se destruye el midlet
    protected void destroyApp(boolean incondicional) {
	System.out.println("Paso a estado Destruido");
    }

    //Metodo para el tratamiento de datos de teclado 
    public void commandAction(Command c, Displayable d) {
	//Miramos si nos salimos o mostramos la alerta
	if (c ==salir) {
	   destroyApp(true);
	   notifyDestroyed();
        } else if (c == continuar) {
	    //creamos la alerta con el titulo, el texto y el tipo escogido
	    switch (tipo.getSelectedIndex()) {
		case 0: alerta=new Alert(titulo.getString(),texto.getString(),null, AlertType.ALARM); break;
		case 1: alerta=new Alert(titulo.getString(),texto.getString(),null, AlertType.CONFIRMATION); break;
		case 2: alerta=new Alert(titulo.getString(),texto.getString(),null, AlertType.ERROR); break;
		case 3: alerta=new Alert(titulo.getString(),texto.getString(),null, AlertType.INFO); break;
		case 4: alerta=new Alert(titulo.getString(),texto.getString(),null, AlertType.WARNING); break;	    
	     default:
  		   alerta=new Alert(titulo.getString(),texto.getString(),null, AlertType.INFO); 
	    }
	   
	    //Le ponemos el tiempo a la alerta
	    if ((tiempo.getSelectedIndex() == 0) || (segundos.getValue()==0) )
		alerta.setTimeout(Alert.FOREVER);
	    else
		alerta.setTimeout(segundos.getValue()*1000);

	    //Mostramos la alerta
	    display.setCurrent(alerta);
        } else System.out.println("Otro comando pulsado");
        
   } 

    //Metodo para el tratamiento de cambios en los items 
    public void itemStateChanged(Item item) {
	//Si cambia el tiempo-> cambiamos los segundos
	if (item == tiempo) {
	    if (tiempo.getSelectedIndex() == 0) {
		segant=segundos.getValue();
		segundos.setValue(0);
	    } else 
		segundos.setValue(segant);
		//Si cambia los segundos-> cambiamos el tiempo
	} else if (item == segundos) {
	    if (segundos.getValue() == 0) 
		tiempo.setSelectedIndex(0,true);
	    else 
		tiempo.setSelectedIndex(1,true);
	    
	} else System.out.println("Otro item cambiado pulsado");
    }
}

4.5.- La clase List

La clase proporciona una lista de elementos de forma parecida al ítem ChoiceGroup pero no para integrarlo en un Form sino para ser usado directamente en el Display. Esta clase implementa la interfaz Choice por lo que su uso es análogo a la clase ChoiceGroup que también implementa dicho interfaz.

Los constructores de List son:

public List(String title, int listType)
public List(String title, int listType, String[] stringElements, Image[] imageElements)

El primero sólo especifica el título que tendrá la lista y el tipo de lista que será. El segundo constructor además tiene un array con los elementos de esa lista y otro array con las imágenes asociadas a esos elementos de la lista. El segundo parámetros de ambos constructores es el tipo de lista y puede tomar los siguientes valores:

Con las métodos insert() y append() podremos insertar o añadir elementos a la lista. Con las funciones delete() o deleteAll() podremos borrar elementos de la lista, mientras que con set() podremos modificar un elemento y con size() obtendremos el número de elementos de la lista. Para verlos con más detalle se puede echar un vistazo a la sección 4.3.1.

Veamos un ejemplo donde se van a poder un ejemplo de menús hechos con la clase List:

Ejemplo8.java Ejemplo de List

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


public class Ejemplo8 extends MIDlet implements CommandListener {
    public static final int CONECTAR= 0;
    public static final int ESTADO= 1;
    public static final int INSERTAR= 2;
    public static final int DESCONECTAR= 3;
    public static final int MENU= 4;

    private Display display;

    private Alert alerta;
    private List menu;
    private TextBox estado;
    private Form form;

    private TextField server;
    private TextField area;
    private ChoiceGroup riesgo; 
    private ChoiceGroup aficiones; 

    private Command salir; 
    private Command continuar; 

    private int estado_actual;

    //Constructor
    public Ejemplo8(  ) {
	estado_actual=MENU;

	//Cogemos el display
	display=Display.getDisplay(this);

        //Creamos los items Form
 	  //un item para preguntar el nombre del servidor
          server= new TextField("Servidor:","",10,TextField.URL);
 	  //un item para mostrar info
	  estado =new TextBox("Estado","Sin Conexion", 400, TextField.ANY);
 	  //un item para pedir un area
	  area =new TextField("Area ID","0", 10, TextField.NUMERIC);
 	  //un item para indicar un riesgo
          riesgo= new ChoiceGroup("Riesgo:",ChoiceGroup.EXCLUSIVE);
	  riesgo.append("Bajo",null);
	  riesgo.append("Normal",null);
	  riesgo.append("Alto",null);

        //Creamos el menu y le anadimos las opciones
        menu = new List ("Ejemplo 8",List.EXCLUSIVE);
        menu.append("Conectar",null); 
        menu.append("Pedir Datos",null); 
        menu.append("Introducir Datos",null); 
        menu.append("Desconectar",null); 

	//creamos un alert
	alerta= new Alert("Error","No hay conexion",null, AlertType.ERROR); 
	alerta.setTimeout(Alert.FOREVER);

	//creamos un form
	form = new Form ("Menu Conectar");

	//Creamos los comandos a usar
	salir=new Command("Salir",Command.EXIT, 3);
	continuar=new Command("Continuar",Command.OK, 1);

        //anadimos los comandos al List y activamos el oyente
	menu.addCommand(continuar);
	menu.addCommand(salir);
        menu.setCommandListener(this);

	//Anadimos al form sus comandos
	form.addCommand(continuar);
	form.addCommand(salir);
        form.setCommandListener(this);

        //anadimos al textBox sus comandos
	estado.addCommand(salir);
        estado.setCommandListener(this);
    }
 
    //Metodo que se llama cuando pasamos de Pausado a Activo
    protected void startApp(  ) {
        display.setCurrent(menu);
    }
 
    //Metodo que se llama cuando pasamos de Activo a Pausado
    protected void pauseApp(  ) {
    }
 
    //Metodo que se llama cuando se destruye el midlet
    protected void destroyApp(boolean incondicional) {
    }

    //Metodo para el tratamiento de datos de teclado 
    public void commandAction(Command c, Displayable d) {

	if (estado_actual == MENU ) {
	    //si estamos en el menu, nos salimos o nos vamos
	    //a la opcion escogida
	    if (c ==salir) {
		destroyApp(true);
		notifyDestroyed();
	    } else if (c ==continuar) {
		switch ( menu.getSelectedIndex() ){
		 case CONECTAR: conectar(); break;
		 case ESTADO: listar();break;
		 case INSERTAR: insertar();break;
		 case DESCONECTAR: desconectar();break;
		}
	    } else System.out.println("Otro comando pulsado");

	} else {
	    //si no estamos en el menu, nos vamos al menus o procesamos
	    //los datos
	    if (c == salir) {
	
		muestraMenu();
	    } else if (c ==continuar) {
		switch ( estado_actual ){
		 case CONECTAR: listar();break;
		 case ESTADO: muestraMenu();break;
		 case INSERTAR: listar();break;
		 case DESCONECTAR: muestraMenu();break;
		}
	    } else System.out.println("Otro comando pulsado");
	}
    }

    public void conectar(){
	estado_actual=CONECTAR; 
	//cambiamos el titulo del form
	form.setTitle("Menu Conectar");
	//Borramos todos los items del form
	while (form.size()>0)
	    form.delete(0);
	form.append(server);

	display.setCurrent(form);
    }

    public void insertar(){
	estado_actual=INSERTAR;
	//cambiamos el titulo del form
	form.setTitle("Menu Insertar");
	//Borramos todos los items del form
	while (form.size()>0)
	    form.delete(0);
	form.append(area);
	form.append(riesgo);

	display.setCurrent(form);
    }
ú
    public void muestraAlerta(String titulo, String texto){
	alerta.setTitle(titulo);
	alerta.setString(texto);
	//mostramos un alert
	display.setCurrent(alerta);
    }

    public void desconectar(){
	estado_actual=DESCONECTAR;
	//mostramos un alert
	muestraAlerta("Desconectar","No se esta conectado a ningun servidor.");
	estado_actual=MENU;
    }

    public void listar(){
	estado_actual=ESTADO;
	//mostramos el textbox
	display.setCurrent(estado);
    }

    public void muestraMenu(){
	//mostramos el List
	estado_actual=MENU;
	display.setCurrent(menu);
    }
}

4.6.- La clase TextBox

Nos permite editar un campo de texto, normalmente mas de una linea y fuera un Form a diferencia del ítem TextField que, normalmente, sólo nos permite editar una línea y dentro de un Form. El constructor para esta clase es:

public TextBox(String title, String text, int maxSize, int constraints);

El primer parámetro indica el título que aparece en la pantalla, el segundo el texto con el que puede estar inicializado el TextBox, el tercer nos indica en número máximo de carácteres que admite y el tercero son las restricciones del campo de texto. Las restricciones (constraints) ya las vimos en la clase TextField (sección 4.3.3) y son TextField.ANY, TextField.EMAILADDR,TextField.NUMERIC,TextField.PHONENUMBER,TextField.URL y TextField.PASSWORD. Para acceder o modificar las restricciones también tenemos los métodos public int getConstraints() y setConstraints(int constraints)

Para leer o modificar el texto del TextBox tenemos los siguientes métodos:

public void setString(String text)
public String getString()
public int getChars(char[] data)

Que tienen la misma funcionalidad que los vistos en TextField.

Con las siguientes funciones podremos leer y modificar el número de carácteres máximos que admite nuestro TextBox:

public int getMaxSize()
public void setMaxSize(int maxSize)

Mientras que con la función size() podremos saber el número de carácteres que hay escritos.

La clase TextBox también nos va a permitir realizar una serie de cambios dentro del texto que se puede editar, siempre que sean consistentes con las restricciones y para ello tenemos los siguientes métodos:

public void delete(int offset, int length);
public void insert(char []chars, int offset, int length, int position);
public void insert(String src, int position);
public void setChars(char []chars, int offset, int length);
public int getCaretPosition();

Que operan igual a las de TextField.

4.7.- Ejercicios

Ejercicio: Hacer una calculadora simple, que nos pida dos números y una operación y nos muestre el resultado.

Ejercicio: Haz un Form probando todos los Layout que soporta ImageItem.

Ejercicio: Haz un Form que pida los datos de un alumno: Nombre, Apellidos, Fecha de Nacimiento, DNI, email, Sexo, Aficiones, teléfono, un nombre de usuario (login) y una contraseña. Una vez recogidos los datos, crear un TextBox que los muestre todos. Para mostrar los posibles fallos introducidos se debe utilizar Alert (por ejemplo, que un campo no esté relleno).

Ejercicio: Hacer un sistema de menús de un juego (con List), donde podamos elegir, la dificultad de 1 a 10 con un Gauge, el nombre del jugador, empezar el juego, y lista de mejores puntuaciones. Para mostrar los posibles fallos introducidos se debe utilizar Alert (por ejemplo, empezar el juego sin haber dado un nombre).

Ejercicio: Hacer un sistema de menús de un programa (con List), donde podamos elegir: insertar, borrar, modificar, enviar y listar (ambas opciones tienes que estar también disponibles en los comandos). En insertar debemos poder insertar un alumno (ejercicio anterior), en borrar nos pide un DNI de un alumno y debemos de borrarlo, en listar tenemos que mostrar una lista con todos los alumnos, en enviar, nos tiene que permitir introducir una dirección de email, y en modificar nos debe permitir modificar un alumno (igual que en insertar pero con los campos inicializados). Usar una clase para almacenar cada alumno y un vector para almacenarlos todos.