



(115 opiniones)
Container 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.
El AWT proporciona cuatro clases de Contenedores:
Además de estos Contenedores, la clase Applet también es un Contenedor, es un subtipo de la clase Panel y puede tener Componentes.
Es una superficie de pantalla de alto nivel (una ventana). Una instancia de la clase Window no puede estar enlazada o embebida en otro Contenedor. Una instancia de esta clase no tiene ni título ni borde.
Es una superficie de pantalla de alto nivel (una ventana) con borde y título. Una instancia de la clase Frame puede tener una barra de menú. Una instancia de esta clase es mucho más aparente y más semejante a lo que nosotros entendemos por ventana.
Es una superficie de pantalla de alto nivel (una ventana) con borde y título. Una instancia de la clase Dialog no puede existir sin una instancia asociada de la clase Frame.
Es un Contenedor genérico de Componentes. Una instancia de la clase Panel, simplemente proporciona un Contenedor al que ir añadiendo Componentes.
Antes de poder incorporar Componentes a la interface de usuario que se desea implementar, el programador debe crear un Contenedor. Cuando se construye una aplicación, el programador debe crear en primer lugar una instancia de la clase Window o de la clase Frame. Cuando lo que se construye es un applet, ya existe un Frame (la ventana del navegador). Debido a que la clase Applet está derivada de la clase Panel, el programador puede ir añadiendo Componentes directamente a la instancia que se crea de la clase Applet.
En el siguiente ejemplo se crea un Frame vacío. El título del Frame, que corresponderá al título de la ventana, se fija en la llamada al constructor. Un Frame inicialmente está invisible, para poder verlo es necesario invocar al método show():
import java.awt.*;
public class Ejemplo1 {
public static void main( String args[] ) {
Frame f = new Frame( "Ejemplo 1" );
f.show();
}
}
En el código de ejemplo que sigue, extendemos el código anterior para que la nueva clase sea una subclase de la clase Panel. En el método main() de esta nueva clase se crea una instancia de ella y se le incorpora un objeto Frame llamando al método add(). El resultado de ambos ejemplos es idéntico a efectos de apariencia en pantalla:
import java.awt.*;
public class Ejemplo2 extends Panel {
public static void main( String args[] ) {
Frame f = new Frame( "Ejemplo 2" );
Ejemplo2 ej = new Ejemplo2();
f.add( "Center",ej );
f.pack();
f.show();
}
}
Derivando la nueva clase directamente de la clase Applet en vez de Panel, nuestro ejemplo puede ahora ejecutarse tanto como una aplicación solitaria como dentro de una página HTML en un navegador. El código siguiente muestra esta circunstancia:
import java.awt.*;
public class Ejemplo3 extends java.applet.Applet {
public static void main( String args[] ) {
Frame f = new Frame( "Ejemplo 3" );
Ejemplo3 ej = new Ejemplo3();
f.add( "Center",ej );
f.pack();
f.show();
}
}
Un objeto Window, y en algunos casos incluso un objeto Dialog, pueden reemplazar al objeto Frame. Son Contenedores válidos y los Componentes se añaden en ellos del mismo modo que se haría sobre un Frame.
Para que la interface sea útil, no debe estar compuesta solamente por Contenedores, éstos deben tener Componentes en su interior. Los Componentes se añaden al Contenedor invocando al método add() del Contenedor. Este método tiene tres formas de llamada que dependen del manejador de composición o layout manager que se vaya a utilizar sobre el Contenedor.
En el código siguiente, incorporamos dos botones al código del último ejemplo. La creación se realiza en el método init() porque éste siempre es llamado automáticamente al inicializarse el applet. De todos modos, al inciarse la ejecución se crean los botones, ya que el método init() es llamado tanto por el navegador como por el método main():
import java.awt.*;
public class Ejemplo4 extends java.applet.Applet {
public void init() {
add( new Button( "Uno" ) );
add( new Button( "Dos" ) );
}
public static void main( String args[] ) {
Frame f = new Frame( "Ejemplo 4" );
Ejemplo4 ej = new Ejemplo4();
ej.init();
f.add( "Center",ej );
f.pack();
f.show();
}
}
PANELES
La clase Panel es 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 applet 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 (el de defecto), 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 tanto al applet) todos los eventos que sobre él ocurran. Esto que puede parecer un poco rebuscado, obedece al esquema arquitectónico del AWT; se trata del bien conocido esquema de separación interface/implementación que establece por un lado una clase de interface y por otro distintas clases de implementación para cada una de las plataformas elegidas.
El uso de Paneles permite que las aplicaciones puedan utilizar múltiples layouts, es decir, que la disposición de los componentes sobre la ventana de visualización pueda modificarse con mucha flexibilidad. Permite que cada Contenedor pueda tener su propio esquema de fuentes de caracteres, color de fondo, zona de diálogo, etc.
Podemos, por ejemplo, crear una barra de herramientas para la zona superior de la ventana de la aplicación o incorporarle una zona de estado en la zona inferior de la ventana para mostrar información útil al usuario. Para ello vamos a implementar dos Paneles:
class BarraHerram extends Panel {
public BarraHerram() {
setLayout( new FlowLayout() );
add( new Button( "Abrir" ) );
add( new Button( "Guardar" ) );
add( new Button( "Cerrar" ) );
Choice c = new Choice();
c.addItem( "Times Roman" );
c.addItem( "Helvetica" );
c.addItem( "System" );
add( c );
add( new Button( "Ayuda" ) );
}
}
class BarraEstado extends Panel {
Label texto;
Label mas_texto;
public BarraEstado() {
setLayout( new FlowLayout() );
add( texto = new Label( "Creada la barra de estado" ) );
add( mas_texto = new Label( "Información adicional" ) );
}
public void verEstado( String informacion ) {
texto.setText( informacion );
}
}
Ahora, para dar funcionalidad, debemos crear los objetos correspondientes a la barra de herramientas y a la barra de estado con new; al contrario que en C++, en Java todos los objetos deben ser creados con el operador new:
add( "North",tb = new ToolBar() ); add( "South",sb = new StatusBar() );
También vamos a incorporar un nuevo evento a nuestro controlador, para que maneje los eventos de tipo ACTION_EVENT que le llegarán cuando se pulsen los botones de la barra de herramientas o se realice alguna selección, etc.
case Event.ACTION_EVENT:
{
be.verEstado( evt.arg.toString() );
return true;
}
Cuando la aplicación reciba este tipo de evento, alterará el contenido de la barra de estado para mostrar la información de la selección realizada o el botón pulsado.
Al final, la apariencia de la aplicación en pantalla es la que presenta la figura anterior.
DIALOGOS Y VENTANAS
Una Ventana genérica, Window, puede utilizarse simplemente para que sea la clase padre de otras clases y se puede intercambiar por un Diálogo, Dialog, sin pérdida de funcionalidad. No se puede decir lo mismo de un Frame.
Se podría crear un menú pop-up con una Ventana, pero lo cierto es que en esta versión del JDK hay un montón de bugs y no merece la pena el enfrascarse en el intento. No obstante, hay ciertos métodos que están en la clase Window y que no están presentes en otras clases que pueden resultar interesantes y necesitar una Ventana si queremos emplearlos. Son:
Un Diálogo es una subclase de Window, que puede tener un borde y ser modal, es decir, no permite hacer nada al usuario hasta que responda al diálogo. Esto es lo que se usa en las cajas de diálogo "Acerca de...", en la selección en listas, cuando se pide una entrada numérica, etc.
El código Java que se expone a continuación, implementa el diálogo Acerca de para la aplicación. Esta clase se crea oculta y necesitaremos llamar al método show() de la propia clase para hacerla visible.
class AboutDialog extends Dialog {
static int HOR_TAMANO = 300;
static int VER_TAMANO = 150;
public AboutDialog( Frame parent ) {
super( parent,"Acerca de...",true );
this.setResizable( false );
setBackground( Color.gray );
setLayout( new BorderLayout() );
Panel p = new Panel();
p.add( new Button( "Aceptar" ) );
add( "South",p );
resize( HOR_TAMANO,VER_TAMANO );
}
public void paint( Graphics g ) {
g.setColor( Color.white );
g.drawString( "Aplicación Java con AWT",
HOR_TAMANO/4,VER_TAMANO/3 );
g.drawString( "Versión 1.00",
HOR_TAMANO/3+15,VER_TAMANO/3+20 );
}
public boolean handleEvent( Event evt ) {
switch( evt.id ) {
case Event.ACTION_EVENT:
{
if( "Aceptar".equals( evt.arg ) )
{
hide();
return true;
}
}
default:
return false;
}
}
}
La ventana que aparece en pantalla generada por la clase anterior es la que muestra la figura:
Las aplicaciones independientes deberían heredar tomando como padre la ventana principal de esa aplicación. Así pueden implementar la interface MenuContainer y proporcionar menús.
No hay razón aparente para que sea una subclase de la clase Frame, pero si se quiere proporcionar funcionalidad extra, sí debería serlo, en vez de serlo de su padre: Window. Esto es así porque Frame implementa la interface MenuContainer, con lo cual tiene la posibilidad de proporcionar menús y cambiar el cursor, el icono de la aplicación, etc.
Un ejemplo más complicado de aplicación gráfica basada en el AWT es el convertidor de decimal a binario/octal/hexadecimal/base36, Convertidor.java, cuya presentación en pantalla es la que muestra la figura siguiente.
En la construcción de esta nueva aplicación se utilizan elementos que se presentan en profundidad en secciones posteriores de este Tutorial.
CREAR EL MARCO DE LA APLICACION
El Contenedor de los Componentes es el Frame. También es la ventana principal de la aplicación, lo que hace que para cambiar el icono o el cursor de la aplicación no sea necesario crear métodos nativos; al ser la ventana un Frame, ya contiene el entorno básico para la funcionalidad de la ventana principal.
Vamos a empezar a crear una aplicación básica, a la que iremos incorporando Componentes. Quizás vayamos un poco de prisa en las explicaciones que siguen; no preocuparse, ya que lo que no quede claro ahora, lo estará más tarde. El problema es que para poder profundizar sobre algunos aspectos de Java, necesitamos conocer otros previos, así que proporcionaremos un ligero conocimiento sobre algunas características de Java y del AWT, para que nos permitan entrar a fondo en otras; y ya conociendo estas últimas, volveremos sobre las primeras. Un poco lioso, pero imprescindible.
En el archivo AplicacionAWT.java, se encuentra el código completo de la aplicación que vamos ir construyendo a lo largo de este repaso general por las características de que dispone el AWT.
Comenzaremos el desarrollo de nuestra aplicación básica con AWT a partir del código que mostramos a continuación:
import java.awt.*;
public class AplicacionAWT extends Frame {
static final int HOR_TAMANO = 300;
static final int VER_TAMANO = 200;
public AplicacionAWT() {
super( "Aplicación Java con AWT" );
pack();
resize( HOR_TAMANO,VER_TAMANO );
show();
}
public static void main( String args[] ) {
new AplicacionAWT();
}
}
La clase anterior es un Frame, ya que extiende esa clase y hereda todas sus características. Tiene un método, el constructor, que no admite parámetros.
Además, se hace una llamada explícita al constructor super, es decir, al constructor de la clase padre, para pasarle como parámetro la cadena que figurará como el título de la ventana.
La llamada a show() es necesaria, ya que por defecto, los Contenedores del AWT se crean ocultos y hay que mostrarlos explícitamente. La llamada a pack() hace que los Componentes se ajusten a sus tamaños correctos en función del Contenedor en que se encuentren situados.
La ejecución de la aplicación mostrará la siguiente ventana en pantalla:
Los atributos fundamentales de la ventana anterior son:
|