JavaBeans de interfaz gráfico

(Octubre de 2005)

Introducción

La idea es realizar componentes visuales (controles) al estilo de lo que ofrecen IDEs como .Net de Microsoft o Delphi de Borland:

Los componentes se diseñan aplicando el concepto de "amplia cobertura del servicio", es decir, teniendo en cuenta que el control debe servir a diferentes necesidades y usuarios (programadores), unos serán experimentados, otros novatos; unos necesitan un servicio más amplio y otros unas pocas utilidades. La regla de sensatez es "curarse en salud" y ofrecer un servicio amplio, lo que implica ofrecer una buena cantidad de propiedades y eventos.

Reglas de escritura de beans

  1. Para informar al exterior sobre las propiedades del bean hay dos métodos: primero escribir un método setXXX() y otro getXXX() para cada propiedad; en segundo lugar usar archivos BeanInfo. Nosotros nos centraremos en el primer método: para cada propiedad "prop" crearemos un método getProp() que devuelve el valor de la propiedad y un método setProp() que cambia el valor de la propiedad. Los IDE deducen la propiedad a partir de esta convención de nombres.

    Estos métodos serán públicos y lo normal es que la clase tenga un atributo asociado:
    
    	public class JTextFieldRest extends JTextField {
    	   private int ancho;            // Ancho máximo de la cadena introducida por usuario
    
    	   public int getAncho() {
    	      return ancho;
    	   }
    	   public void setAncho( int ancho ) {
    	      this.ancho = ancho;
    	   }
    	....
    	
    El uso de atributos (como en nuestro ejemplo ' int ancho') es lo más común, pero no imprescindible, es decir, podría darse el caso (raro) de tener un bean con la propiedad 'prop', con lo que debemos definir setProp() y getProp(), sin que ello implique tener un atributo en la definición de la clase (tipo atributo;).


  2. Esta regla no es obligatoria pero es conveniente para permitir que el IDE pueda crear instancias del bean: definir un constructor sin argumentos.


  3. La clase implementa el interfaz Serializable. Tampoco es obligatorio, pero resulta conveniente si se quiere guardar el bean entre sesiones. En nuestro ejemplo implementamos dicho interfaz ya que lo implementa la clase madre (JTextField). Por cierto, la hoja de propiedades de nuestro bean mostrará tanto las propiedades de la propia clase como las de la clase madre. Lo mismo es aplicable a la hoja de eventos.

Nuestro ejemplo

Nuestro ejemplo es un campo de texto en el que podemos restringir el juego de caracteres que el usuario puede teclear y el ancho del texto. Esto no resulta extraño, ya que puede haber campos de un formulario que no permiten letras mayúsculas, en otros casos se permite sólo números y signos o en otros el ancho de lo que escribe el usuario esta limitado a lo que se puede guardar en la base de datos.

En nuestro caso lo que hacemos es:

El código fuente:


package docen_javabean01;

import javax.swing.JTextField;
import java.awt.event.KeyEvent;
import javax.swing.KeyStroke;

/****************************************************************************
 * Campo de texto en el que podemos restringir el juego de caracteres
 * validos y el ancho del texto
 ***************************************************************************/
public class JTextFieldRest extends JTextField {
   private String caracteres;         // Cadena de caracteres válidos
   private int ancho;                 // Ancho máximo de la cadena introducida por usuario

   /*************************************************************************
    * Constructor que toma la cadena de caracteres validos y el ancho (length) de
    * parametros.properties.
    * Argumentos:
    *  1. Cadena de caracteres válidos. Si la cadena esta vacia o es null, cualquier caracter es válido.
    *  2. Límite máximo de la cadena. Si es cero, no hay límite.
    *  3. Texto que aparece al iniciarse. Si Texto es null, no se usa setText()
    *  4. Si ActionCommand es null, no se usa
    *************************************************************************/
   public JTextFieldRest( String CaracteresValidos, int Ancho, String Texto, String ActionCommand ) {
      caracteres = CaracteresValidos;
      ancho = Ancho;
      setText(Texto);
      setActionCommand(ActionCommand);
   }

   /*************************************************************************
    * Constructor vacio. Ver respuesta documentación del primer constructor
    ************************************************************************/
   public JTextFieldRest() {
     this( "", 0, "", null);
   }

   /*** Devuelve cadena de caracteres permitidos ***/
   public String getCaracteres() {
      return caracteres;
   }
   /*** Define cadena de caracteres permitidos ***/
   public void setCaracteres( String CaracteresValidos ) {
      caracteres = CaracteresValidos;
   }
   /*** Devuelve ancho limite de la cadena ***/
   public int getAncho() {
      return ancho;
   }
   /*** Define ancho limite de la cadena ***/
   public void setAncho( int ancho ) {
      this.ancho = ancho;
   }

   /*************************************************************************
    Sobreescribimos este método para determinar (por el booleano que devuelve) si el
    caracter se escribe.
    *************************************************************************/
    protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {


       if ( ancho > 0 && getText().length() > ancho )  // Si supera el ancho, no se escribe
	  return false;

       // Si hay cadena de caracteres válidos y la tecla (e) es válida, se escribe
       if ( caracteres != null && caracteres.length() > 0 ) {
	  if ( esTeclaValida( e ) )
	     return super.processKeyBinding(ks, e, condition, pressed); // Se escribe
       }

       return false;  // No se escribe
   }

   /*************************************************************************
   * Devuelve true si es una tecla valida
   *************************************************************************/
   protected boolean esTeclaValida( KeyEvent e ) {
      //System.out.println( "char:"+ e.getKeyChar() + "  code:" + e.getKeyCode() );

      //// Para que permita el BACK SPACE
      if (KeyEvent.VK_BACK_SPACE == e.getKeyCode() || e.getKeyChar() == '') {
	  return true;
      }
      //// Para que permita izquierda, derecha, etc.
      switch (e.getKeyCode()) {
	 case (KeyEvent.VK_ALT):
	 case (KeyEvent.VK_BACK_QUOTE):
	 case (KeyEvent.VK_BACK_SLASH):
	 case (KeyEvent.VK_BACK_SPACE):
	 case (KeyEvent.VK_CONTROL):
	 case (KeyEvent.VK_CLEAR):
	 case (KeyEvent.VK_COPY):
	 case (KeyEvent.VK_CUT):
	 case (KeyEvent.VK_DELETE):
	 case (KeyEvent.VK_ENTER):
	 case (KeyEvent.VK_HOME):
	 case (KeyEvent.VK_END):
	 case (KeyEvent.VK_INSERT):
	 case (KeyEvent.VK_LEFT):
	 case (KeyEvent.VK_PASTE):
	 case (KeyEvent.VK_RIGHT):
	 case (KeyEvent.VK_TAB):
	 return true;
      }

      //// Si el caracter está en la cadena, se escribe
      for ( int i = 0; i < caracteres.length(); i++) {
	 if (e.getKeyChar() == caracteres.charAt(i))
	    return true;
      }

      return false;
   }
}
	

Empaquetar beans en archivos JAR

La mayor parte de los entornos integrados de desarrollo (IDE) requieren que el bean sea empaquetado en un archivo jar con su correspondiente archivo manifiesto (manifest).

En primer lugar empezaremos con el archivo Manifest. En este archivo sólo hay que hacer referencia a los bean que vayamos a instalar en la paleta de herramientas del IDE. Este archivo tiene una estructura determinada:


Manifest-Version: 1.0

Name: JTextFieldRest.class
Java-Bean: True

Name: xCtrl.class
Java-Bean: True
	

Se debe asegurar que existe una línea vacía entre las entradas y que la última línea termina en un caracter de salto de línea. Además no debe haber espacios en blanco al final de las líneas. El archivo manifiesto tiene la extensión mf.

Los bean pueden asociarse con una imagen, que aparecerá en la paleta de componentes. La image es un GIF o un JPG de 64x64 píxeles con el mismo nombre que el bean. Esta imagen, al igual que cualquier clase que utilice el bean, se debe empaquetar en al archivo jar.

El archivo JAR se realiza de forma sencilla:


jar cvfm JTextFieldRest.jar docen_javabean01/JTextFieldRest.mf classes\docen_javabean01\JTextFieldRest.class
	



Volver al índice