No pretendo aquí establecer disputas con C++, Smalltalk u otros lenguajes, como tampoco deseo abundar en comparaciones tediosas entre entornos de desarrollo Java (o mejor C++), así que, por lo que a este artículo respecta, Java es inevitablemente fabuloso, y en lo que afecte a un entorno (como ejemplos e ilustraciones) éste será, cuando no se indique lo contrario, Microsoft Visual J++: el autor dixit. De cualquier forma, no espere el lector ungüentos milagrosos ni imposiciones de manos: el estudio de los applets no será sino el examen de una particular estructuración de eventos inserta en una discutida biblioteca gráfica, con un fondo de Internet y unas gotas de angostura: el resto es, como siempre, tarea del programador: es decir, uno puede aprender a construir un applet igual que puede enseñarse a codificar un diálogo en un entorno gráfico, pero, ¡ah!, la inteligencia de esa pieza siempre dependerá de la habilidad y experiencia del programador respecto del lenguaje usado y de sus recursos. En fin: un buen applet será únicamente resultado del trabajo de un buen programador Java (ó C++, claro). ¿QUÉ ES UN APPLET? La lógica borrosa y la ciencia infusa se dan cita en éste barbarismo de impotable traducción[1]. La definición más extendida, bien resumida por Patrick Naughton, afirma que un applet es una “pequeña aplicación accesible en un servidor Internet, que se transporta por la red, se instala automáticamente y se ejecuta in situ como parte de un documento web”. Claro que así la definición la establece el entorno (Internet, el WWW, etc.). En realidad un applet es una aplicación pretendidamente corta (nada impide que ocupe 1 Gb, a no ser el deseo de su transporte por una red y una mente equilibrada) basada en un formato gráfico sin representación independiente: esto es, se trata de un elemento de composición a embeber en otras aplicaciones, que actuarán en calidad de “contexto del applet”. Es, pues, un componente en su sentido estricto (y jerárquico, como veremos). ¿Un ejemplo en otro ámbito? Imaginemos que una empresa, cansada de empezar siempre a codificar desde cero, diseña un formulario con los datos básicos de una persona física/jurídica (nombre, direcciones, etc.): tal formulario no es un diálogo per se, pero se podría integrar en diálogos de clientes, proveedores, empleados, etc. El hecho que se integre estática (embebido en un ejecutable) o dinámicamente (intérpretes, DLLs, etc.) en absoluto afecta a la esencia de su comportamiento como componente con que aderezar y construir diálogos con sentido autónomo. Pues bien, así es un applet. Lo que ocurre es que, dado que no existe una base siquiera adecuada de aplicaciones industriales Java en que insertar tales aplicaciones, los applets se han construido mayoritariamente, y con gran acierto comercial, como pequeñas aplicaciones interactivas, con movimiento, luces y sonido … ¡en Internet! Claro que esto ha generado una pléyade de páginas web petulantes y ridículas (entre las que en breve se enmarcarán algunas de las mías[2]), donde los applets y otros controles activos intentan suplir las carencias intelectuales de sus autores. Y es que incluso los entornos de desarrollo resultan bonitos y atractivos: es el caso de Java Workshop (Beta Developers Release 6) de Sun, donde la construcción de applets mediante la herramienta gráfica Visual Java[3] tiene el agradable aspecto que muestran las figuras. Pero, bueno, volvamos al apasionante mundo del código y de los caracteres. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
INTERNET, HTML Y ESTÁNDARES Dado que los applets están mayormente destinados a ejecutarse en visores web, había que preparar el lenguaje HTML (HyperText Markup Language, una derivación de SGML) para soportar Java, o mejor: los applets. El esquema de marcas de HTML y la evolución del estándar tirada por las mulas de Netscape trocaron fácil la adición de una nueva etiqueta <applet> que permitiera, una vez añadido el correspondiente código gestor en los visores, la ejecución de programas Java en ellos. El problema es que la sintaxis resulta un tanto volátil (por carente de normalización reglada), así que el lector fiará la portabilidad de sus páginas web a diferentes visores no abusando de las opciones que a continuación se detallan en el cuadro que sigue, donde “O” significa optativo, pues lo son las opciones señaladas con el signo “+”: |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
De esta manera el código HTML de una elemental página web con soporte Java quedaría de la siguiente guisa, generado por Microsoft Visual J++ para un applet ridículo: <html> CUESTIONES JERÁRQUICAS ¿Qué es un applet? Pues, a efectos del programador, cualquier clase, u objeto instanciado de cualquier clase[4] que derive-de (extienda) la clase Applet, independientemente de que el resultado sea inteligente o desdichado (Oh, es la misma respuesta a “¿Quién es el presidente del gobierno?”). Resulta así que el AWT[5] ha provisto una clase con un interfaz mínimo para que sirva de base a lo que podría ser un pozo de Babel en Java/Internet. Pero examinemos la jerarquía: |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Así que un applet es, a la vez (debido a la tiranía de las jerarquías de subtipado) un componente, un contenedor de componentes y un panel (nada sustantivo, como veremos más adelante). Por supuesto que no hay espacio para tratar de “Object” (la madre de todos los objetos), pero sí para echarle un vistazo al resto, de forma que el lector asumirá que cuanto se diga para estas superclases de Applet sirve para la clase Applet misma. COMPONENT Se trata de una clase abstracta que representa “todo lo que tiene una posición, un tamaño, puede ser pintado en la pantalla y puede recibir eventos” (MS VJ++). Esta clase es la piedra angular del AWT y posee un largo interfaz de funciones que deberá ser cuidadosamente estudiado, pues tales habrán de ser por lo común sobrecargadas en las clases derivadas (y, por ende, en las clases derivadas de Applet). CONTAINER Esta es una clase abstracta, derivada de “Component”, que representa a cualquier componente que pueda contener otros componentes. Se trata, en esencia, de añadir a la clase “Component” la funcionalidad de adición, sustracción, recuperación, control y organización de otros componentes. Las tres primeras acciones parecen claras, pues se limitan a la adición de los métodos correspondientes: (el ejemplo se supone codificado en el ámbito de una clase de tipo contenedor):
mientras que el control se basa en la gestión de eventos relacionados con el contenedor (como veremos más adelante) y la organización (esto es, el orden y disposición de los componentes respecto del contenedor y de ellos mismos) la gestiona una instancia de LayoutManager o de una clase derivada de ésta. Veámoslo. LAYOUT Java proporciona unos cuantos esquemas predefinidos de disposición de componentes en contenedores. ¿Por qué? La razón es simple: imaginemos que deseamos agrupar objetos de distinto tamaño en celdas de un rejilla virtual: si fiados de nuestro conocimiento de un sistema gráfico determinado codificamos a mano tal disposición deberemos prever el redimensionamiento del applet, su repintado cuando sea cubierto por otra ventana, etc., además de las cuitas relacionadas con el posible cambio de plataforma (uno nunca sabe donde van a ir a para los propios hijos o los applets). Sigamos imaginando, ahora, que un hábil equipo de desarrollo ha previsto las disposiciones gráficas más usadas y ha creado un “gestor” para cada una de tales configuraciones, que se ocupará, de forma transparente para nosotros, de todas esas cuitas de formatos. Bien: estos gestores son instancias de las distintas clases derivadas-de “LayoutManager” y que se detallan a continuación: |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
a la que se pasa como parámetro una instancia de una clase derivada-de (extensión-de) LayoutManager (no olvidemos que ésta es una clase abstracta y, por tanto, no puede instanciarse), bien de las vistas anteriormente bien de las codificadas por algún inquieto codificador compulsivo:
EVENTS Un contenedor “soltado” en un entorno gráfico se convierte en rápido receptor de eventos de todo tipo, singularmente de los relacionados con movimientos del ratón, pulsaciones de teclas, creación/movimiento/destrucción de partes gráficas y, por último, los referidos a acciones del usuario respecto de componentes (elección de un menú, presionado de un botón, etc.). Los eventos de ratón se controlan mediante funciones que provienen de la clase “java.awt.Component”:
al igual que los de pulsación de teclas:
En cuanto a los de movimiento de partes gráficas, ya tendremos tiempo de examinarlos cuando estudiemos la actualización visual de los applets. Quedan, pues, las acciones, y éstas pueden ser captadas mediante la sobrecarga de dos distintos métodos de “Component”: public boolean handleEvent( Event evt ) y la más frecuentemente usada (en lo poco visto, claro): public boolean action( Event evt, Object arg ) Como en la mayoría de bibliotecas gráficas de C++, el mecanismo de devolución de valor es sencillo: si la clase consume el evento simplemente devuelve “true”, pues si el valor de retorno es “false” el AWT entenderá el evento como no consumido y actuará en consecuencia manejándolo. PANEL Esta clase representa el más simple de los contenedores de componentes gráficos. En realidad se trataba de crear una clase no-abstracta (Container sí lo es) que sirviera de base a los applets y a otras pequeñas aplicaciones. La clase Panel consta de dos métodos propios: el constructor, cuyo fin es crear un nuevo Panel con un LayoutManager de tipo FlowLayout, y el método “addNotify()” que, sobrecargando la función del mismo nombre en la clase Container, llama al método createPanel() del ToolKit adecuado, creando así un “PanelPeer”. El AWT enviará así al Panel (y por ende al Applet) todos los eventos que sobre él ocurran. Esto, que puede sonar un poco rebuscado, obedece al esquema arquitectónico de la AWT, principal causa actual de la mayoría de los problemas de Java. En realidad se trata de un bien conocido esquema de separación interfaz/implementación que establece por un lado una clase de “interfaz” y por otro distintas clases de “implementación” para cada una de las plataformas elegidas[7]. APPLET Vale la pena detallar el interfaz de la clase Applet (según MS Visual J++):
de forma que podamos rápidamente pasar a la programación. EL CÓDIGO Examinemos un elemental applet:
La palabra clase “import” es una mezcolanza de “#include” y “namespace” de C++, que hace visibles en nuestro código las clases correspondientes a los paquetes (packages) que se indican. Si tales líneas se omitieran podríamos seguir accediento a las clases necesitadas únicamente cualificándolas con su dirección (path) completa: así para usar Applet, deberíamos codificar “java.applet.Applet”. El hecho, con todo, de que la jerarquía de clases se corresponda con el árbol de directorios da mucho que pensar.
La palabra reservada “extends” indica que la clase “Prueba” es, en este caso, una subclase (deriva) de la clase “Applet”, e “implements” señala que nuestra clase viene obligada a implementar la funcionalidad del “interfaz” Runnable.
Estas son variables de la clase. void muestra( String frase ) { Necesitamos de esta típica función de ayuda (helper function) que evitará la repetición del mismo código en el resto de los métodos, que en el siguiente bloque de código se detallan en estricto orden de ejecución (init, start, paint, stop, destroy): public void init() { Aquí se inicializan las variables, pues éste es el método que primera y únicamente es llamado por el sistema al cargar un applet. public void start() { La función start() es automáticamente llamada cada vez que la zona de visualización en que está ubicado el applet se expone a la visión, a fin de optimizar el uso de los recursos del sistema y no ejecutar algo que no puede ser apreciado (aunque el programador puede variar este comportamiento y hacer que un applet siga activo aun cuando esté fuera del área de visión). Esto es, imaginemos que cargamos un applet en un visor minimizado: el sistema llamará al método init(), pero no a start(), que sí será llamado cuando restauremos el visor (browser) a un tamaño que permita ver el applet. Naturalmente start() se puede ejecutar varias veces: la primera tras init() y las siguientes (pues init() sólo se ejecuta una vez) tras haber aplicado el método stop(). public void paint( Graphics g ) { // dibuja un rectángulo alrededor del área de visión del applet // dibuja la cadena dentro del anterior rectángulo } Entramos aquí de lleno en las cuitas gráficas de la biblioteca AWT. Cada vez que la zona del applet es cubierta por otra ventana (y singularmente la primera vez que se carga el applet), el scroll desplaza el applet fuera de la zona de visión o el applet cambia de posición debido a un redimensionamiento del visor, el sistema llama automáticamente a la función “paint” pasando como argumento un objeto de tipo “Graphics” que delimita la zona a ser pintada (en realidad se pasa una referencia al contexto gráfico en uso) y que, en nuestro caso, representa la ventana del applet en la página web. Sobre este objeto gráfico podemos realizar operaciones, como las que se exponen arriba. public void update( Graphics g ) { Hemos dicho que, en las situaciones detalladas anteriormente que “dañan” la zona de exposición del applet, el sistema llama a la función “paint”, pero en realidad la llamada se realiza a la función “update”, cuyo comportamiento establecido en la clase “Component” es llamar a la función “paint” … ¡tras rellenar el applet con su color de fondo por defecto! Pudiera así parecer que se trata de una función de efecto neutro, pero si la función “paint” cambiara el color de fondo, el usuario percibiría un “flick” de cambio de colores nada agradable. El programador deberá cuidarse por lo común, así, de eliminar este efecto de “limpia primero” sobrecargando la función “update” para que llame únicamente a “paint”. Otra solución sería insertar el código de pintado en una sobrecarga de la función “update” y escribir un método “paint” que sólo llame a “update”. La última solución es usar de la función “setBackground(Color)” en el método “init” para así evitar el efecto visual sin tener que sobrecargar el método “update”. Estas razones son las mismas que aconsejan usar el método “resize” inserto en “init” para evitar el mismo desagradable efecto. public void stop() { La función “stop” es llamada cuando el visor web no incluye en su campo de visión al applet (por ejemplo, cuando abandona la página en que está inserto), de forma que el programador puede aquí paralizar los hilos (threads) que no resulten necesarios respecto de un applet no visible, y luego recuperar su actividad mediante la función “start”. El método “destroy” se llama (siempre después de “stop”) cuando necesitan ser liberados todos los recursos dispuestos por un applet (por ejemplo, cuando se cierra el visor web). Queda notar, entre otras muchas cosas que requerirán del esforzado lector un estudio atento de la biblioteca de clases Java, que se podrá forzar la actualización de un applet (la llamada a “update”) mediante el uso de la función “repaint” (con distintas signaturas que incluyen tiempo de repintado y localización cartesiana, aparte de la mera función sin argumentos). Pero, ojo, AWT posee “cierta inteligencia” (esta conjunción suele resultar nefasta), de forma que si se llama a “update” mediante “repaint” con una frecuencia muy corta, AWT ignorará las llamadas a “update” que estime oportuno, pues considera a esta función un bien escaso. CONSTRUCCIÓN ASISTIDA DE APPLETS Parece prudente esperar que un lenguaje supuestamente avanzado como Java presente un entorno de desarrollo también avanzado, de forma que no tengamos que codificar los applets “a pedal”. Bien, así es, más o menos. Existen muchos entornos de este tipo: Symantec Espresso/Café, Java WorkShop, IBM VisualAge for Java, Microsoft Visual J++, etc., y de entre todos ellos a efectos pedagógicos nos quedaremos, por sus prestaciones y adecuado IDE, con el de Microsoft, que cada vez lo va haciendo mejor. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MSVJ++ permite crear Ficheros de Texto, Plantillas de Recursos y Ficheros de Mapa de Bits, Espacios de Trabajo de Proyectos; y, dentro de estos últimos, bien Project Workspaces bien applets (dispuestos para ejecutarse en la máquina virtual Java) con la ayuda del Wizard: |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
De forma que Visual J++ genera para nosotros una clase PruebaMSJV.class que el entorno nos muestra bien en razón de sus métodos, bien en razón de los ficheros que componen el proyecto: |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
El código fuente Java que Visual J++ genera es, por otro lado, completo, claro y profusamente comentado, de forma que el principiante podrá crear y editar applets con suma facilidad. La integración, por fin, de este entorno con Microsoft Internet Explorer 3.0 (quizá uno de los visores web más utilizados en la actualidad) y la posibilidad de usar controles ActiveX convierte al conjunto en un equipo “a batir”. REFERENCIAS Si el amable lector visita “The Java Books Page” en el web hallará que en agosto-96 existían 53 libros sobre Java y 147 en preparación). Si aplicamos la bondadosa regla del 20/80 obtendremos un total de 160 libros insustanciales o peligrosos, así que … ¡cuidado con los títulos y fíese de los autores! Por mi parte aquí van algunas nuevas referencias (tiempo y artículos habrá para revisar muchas más obras): · Hooked on Java: Creating Hot Web Sites with Java Applets, por Arthur van Hoff, Sami Shaio y Orca Starbuck, 1995, Addison-Wesley, 0-201-48837-X, con CD-ROM. Vuelvo a recomendar aquí este texto por una razón esencial: contiene un catálogo de buenos applets y un CD-ROM para ejecutarlos. Naturalmente las mejores lecciones para construir applets las ha de proporcionar el código de applets bien construidos. · The Java Handbook: The Authoritative Guide to the Java Revolution, por Patrick Naughton, 1996, Osborne McGraw Hill, 0-07-882199-1. Pese al petulante título, éste es quizá el más completo de los títulos de divulgación Java aquí referidos. Naughton cofundó FirstPerson y participó de forma clave en el proyecto “Green” que dio lugar finalmente a Java, así que la información que aquí se da no es producto de la publicidad del momento. En la primera parte se detalla el lenguaje; en la segunda las clases del mismo y en la tercera el diseño detallado de applets (quizá la literatura más precisa que hasta ahora haya leído sobre el tema). El tono es abiertamente anti-C++, pero la gracia es que se pretende justificar cada decisión de Java en razón de las supuestas insuficiencias de C++: así se dice que C++ no es totalmente orientado-a-objetos por execrables razones de compatibilidad y eficiencia (no como Java, claro), y sin embargo se da por sentado que la decisión de Java de no considerar las clases como objetos en favor de la eficiencia es absolutamente encomiable. El libro, con todo, está menos inflado de aire que el de “Hooked on Java” y su lectura resulta divertida y estimulante, sobre todo en los ejemplos de applets (donde se delata, de paso, la insuficiencia clara de la actual versión de la AWT): los applets “Impresionista”, “DynaDraw” y “Poesía en Imanes” se detallan, en capítulos autónomos, con código y explicaciones. Este texto es, pues, buen candidato para su biblioteca. · The Java Primer Plus: Supercharging Web Applications with the Java Programming Language, por Paul M. Týma, Gabriel Torok y Troy Downing, 1996, Wayte Group Press, 1-57169-062-X. Con un título que podría venderse al peso y muy al estilo de la mayoría de los textos de el Grupo Wayte, esta obra intenta un acercamiento general al lenguaje y a las bibliotecas de clases que comprende sin olvidar aspectos como la comparación con C/C++, etc. El libro es muy completo y asequible, constituyendo una suerte de manual de referencia elemental del lenguaje y su entorno, con muchos dibujos bien cuidados y sin entrar en demasiadas profundidades. El CD que regala incorpora la versión 1 del JDK además del código fuente usado en el libro, applets incluidos. Nada nuevo, pero, eso sí, explicado clarito y agradablemente. La parte III se titula “Uso de las capacidades avanzadas de Java” y resulta la más interesante del libro, pues trata de asuntos de red, hilos (threads), estructuras de datos, interfaz con C, gráficos y sonidos. En fin: una lectura de verano (que puede conseguir que deseche ese infausto libro de gestión de empresas del tipo “En busca de la Excelencia XXIII parte” que pensaba atacar). [1] Recapacite el lector que “Java” es a “Café” lo que “Dead President” o “Frog” es a “billete (verde)”: slang (argot) americano. Así que parece que habrá que esperar al Esplanglish. [2] Las adiciones compulsivas que los applets y otros controles están generando necesitarían de un applet al estilo del viejo “Eliza” que simulara un psicólogo rogeriano, de forma que al acceder a una página “moderna” el navegante fuera instado a explayarse acerca de su familia, su salud mental y su situación económico-laboral. [3] He de decir, con todo, que no me acabo de acostumbrar a operar con hot-spots tan al modo web. Y, sobre todo, no me acomodo a operar con tantas versiones beta: pero, claro, es lo único que hay: todo está en fase beta. [4] Parece que un applet es tanto la clase como el objeto, pero es que esto es lo normal (piensen en Coche, Limón, Político, etc.) [5] AWT significa últimamente “Abstract Windows Toolkit” y es, en breve, la biblioteca que permite la codificación gráfica en Java y una de las mayores rémoras del lenguaje. [6] ¿Java soporta múltiples plataformas? Para no caer en la petulancia, yo diría que no. Sería más preciso afirmar que distintas empresas están creando sus motores Java (en su calidad de intérpretes de bytecode Java) en varios entornos y sistemas operativos. [7] Si al lector este esquema le resulta lejano debiera procurarse una cura literaria estudiando el libro de Gamma y otros -La Banda de los Cuatro- “Dessign Patterns”. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Pº. Castellana 188, 14º e · 28046 - Madrid · info@a4devis.com |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||