|
AWT - Componentes (III) |
Anterior | Siguiente |
Una etiqueta (Label) proporciona una forma de colocar texto estático en un panel, para mostrar información fija, que no varía (normalmente), al usuario. La clase Label extiende la clase Component y dispone de varias constantes que permiten especificar la alineación del texto sobre el objeto Label. El ejemplo java1307.java, cuya imagen inicial al ejecutarlo se reproduce en la figura siguiente, es muy simple y muestra el uso normal de los objetos Label. El programa no proporciona ningún control de eventos, porque las etiquetas normalmente no poseen ningún tipo de eventos, aunque hay que recordar que cualquier receptor de eventos de bajo nivel que se pueda registrar sobre la clase Component, también se podrá registrar sobre la clase Label, al ser ésta una subclase de Component. import java.awt.*; import java.awt.event.*; public class java1307 { public static void main( String args[] ) { IHM ihm = new IHM(); } } class IHM { public IHM(){ // Instancia un objeto Label con una cadena para inicializarlo y // que aparezca como contenido en el momento de su creación Label miEtiqueta = new Label( "Texto inicial" ); // Coloca la eqtiqueta sobre el objeto Frame Frame miFrame = new Frame( "Tutorial de Java, AWT" ); miFrame.setLayout( new FlowLayout() ); miFrame.add( miEtiqueta ); miFrame.setSize( 250,150 ); miFrame.setVisible( true ); // Instancia y registra un objeto receptor de eventos de ventana // para concluir la ejecucion del programa cuando el Frame se // cierres por accion del usuario sobre el miFrame.addWindowListener( new Conclusion() ); } } class Conclusion extends WindowAdapter { public void windowClosing( WindowEvent evt ) { // Concluye el programa cuando se cierra la ventana System.exit(0); } } Una zona de dibujo, o lienzo (Canvas), es una zona rectangular vacía de la pantalla sobre la cual una aplicación puede pintar, imitando el lienzo sobre el que un artista plasma su arte, o desde la cual una aplicación puede recuperar eventos producidos por acciones del usuario. La clase Canvas existe para que se obtengan subclases a partir de ella. No hace nada por sí misma, solamente proporciona una forma de implementar Componentes propios. Por ejemplo, un canvas es útil a la hora de presentar imágenes o gráficos en pantalla, independientemente de que se quiera saber si se producen eventos o no en la zona de presentación. Cuando se implementa una subclase de la clase Canvas, hay que prestar atención en implementar los métodos minimumSize() y preferredSize() para reflejar adecuadamente el tamaño de canvas; porque, en caso contrario, dependiendo del layout que utilice el contenedor del canvas, el canvas puede llegar a ser demasiado pequeño, incluso invisible. La clase Canvas es muy simple, consiste en un solo constructor sin argumentos y dos métodos, que son:
En el ejemplo java1308.java, no tiene mucha importancia el indicar el tamaño del canvas, porque el controlador de posicionamiento utilizado, un BorderLayout, ignora los dos parámetros indicativos del tamaño que se han mencionado, y coloca en el Centro del layout el objeto Canvas. El ejemplo muestra el uso de la clase Canvas y cómo se instancian objetos receptores que pueden manipular los objetos fuente sobre los que están registrados, sin necesidad de pasar referencias a esos objetos fuente a la hora de instanciar los objetos receptor. Por lo tanto, no se utilizan constructores parametrizados en la instanciación de los objetos receptores de eventos en este ejemplo. La imagen siguiente muestra la primera apariencia en pantalla cuando se ejecuta la aplicación y se pica con el ratón sobre una posición dentro del canvas. Aparecen cuatro botones, sin funcionalidad alguna, y un objeto Canvas verde, sobre el objeto Frame; las coordenadas aparecen por haber sido pulsado el botón del ratón. Los botones están ahí simplemente para que se vea que el Frame puede contener más cosas que el Canvas. Los cuatro botones están colocados en los bordes del Frame, utilizando un BorderLayout como controlador de posicionamiento. El Canvas aparece situado en el centro del Frame. Cuando se pulsa el botón del ratón con el cursor en el interior del canvas, aparecerán en pantalla las coordenadas en que se encuentra el ratón en el momento de la pulsación. El origen de los eventos del ratón es el objeto Canvas. No se registran receptores de eventos sobre el Frame ni sobre los botones, por lo que si se pica sobre éstos, o sobre la zona de separación entre los componentes, no sucederá nada. Sin embargo, sí se controla el botón de cierre del Frame, de forma que si se pulsa sobre él, concluirá la ejecución del programa y el control volverá al sistema operativo. import java.awt.*; import java.awt.event.*; // Se crea una subclase de Canvas para poder sobrescribir el método // paint() y poder cambiar el fondo a color verde class MiCanvas extends Canvas { int posicionX; int posicionY; public MiCanvas() { this.setBackground( Color.green ); } // Se sobrescribe el método paint() public void paint( Graphics g ) { g.drawString( "" + posicionX + ", " + posicionY, posicionX,posicionY ); } } class java1308 extends Frame { public static void main( String args[] ) { // Se instancia un objeto del tipo de la clase new java1308(); } public java1308() { // Se crea un borderlayout y se fija el espaciado entre los // componentes que va a albergar BorderLayout miLayout = new BorderLayout(); miLayout.setVgap( 30 ); miLayout.setHgap( 30 ); this.setLayout( miLayout ); this.setTitle( "Tutorial de Java, AWT" ); this.setSize( 300,300 ); // Se instancia un objeto de MiCanvas MiCanvas miObjCanvas = new MiCanvas(); // Se añade el objeto MiCanvas creado al Centro del objeto // Frame a través del BorderLayout this.add( miObjCanvas,"Center" ); // Se añaden los botones no-funcionales en los bordes del // objeto Frame a través del BorderLayout this.add( new Button( "Norte" ),"North" ); this.add( new Button( "Sur" ),"South" ); this.add( new Button( "Este" ),"East" ); this.add( new Button( "Oeste" ),"West" ); // Ahora se podrán ver this.setVisible( true ); // Se instancia y registra un objeto receptor de eventos de la // ventana para poder concluir la aplicación cuando el usuario // cierre el Frame Conclusion conclusion = new Conclusion(); this.addWindowListener( conclusion ); // Se instancia y registra un objeto Listener para procesar los // eventos del ratón y poder determinar las coordenadas en que se // encuentra el cursor cada vez que el usuario pulse el botón sobre // el objeto MiCanvas. // El objeto receptor de eventos es instanciado anónimamente y no // tiene ninguna referencia de MiCanvas, ya que no se le pasa nada // en el constructor miObjCanvas.addMouseListener( new ProcRaton() ); } } // Esta es la clase que monitoriza las pulsaciones de los botones del ratón // y presenta las coordenadas en que se encuentra el cursor cuando el usuario // realiza la pulsación con el cursor situado en el interior del objeto para // el cual se ha registrado class ProcRaton extends MouseAdapter { // Se sobrescribe el método mousePressed() para que haga lo que se ha // indicado public void mousePressed( MouseEvent evt ) { // Recoge las coordenadas x e y de la posición del cursor y las // almacena en variables de instancia del objeto MiCanvas. Es necesario // el casting para poder acceder a las variables de instancia ((MiCanvas)evt.getComponent()).posicionX = evt.getX(); ((MiCanvas)evt.getComponent()).posicionY = evt.getY(); // Se presentan las coordenadas en pantalla evt.getComponent().repaint(); } } // Concluye la ejecucion de la aplicacion cuando el usuario cierra la // ventana, porque se genera un evento windowClosing class Conclusion extends WindowAdapter { public void windowClosing( WindowEvent evt ) { System.exit( 0 ); } } Este programa es muy similar al que sirve de ejemplo de explicación de la clase Frame, que presenta las coordenadas del cursor directamente sobre el área cliente de un objeto Frame. Hay algunas sentencias de código que merece la pena revisar un poco más detenidamente. El primer trozo interesante de código es el que se utiliza para conseguir una subclase de la clase Canvas, para poder sobrescribir el método paint() y también hacer que el objeto sea verde desde el primer momento en que es instanciado. class MiCanvas extends Canvas { int posicionX; int posicionY; public MiCanvas() { this.setBackground( Color.green ); } // Se sobrescribe el método paint() public void paint( Graphics g ) { g.drawString( "" + posicionX + ", " + posicionY, posicionX,posicionY ); } } El siguiente fragmento interesante de código es el usado para crear un BorderLayout, con separaciones (gaps) horizontal y vertical, para el objeto Frame. Aunque el controlador de posicionamiento por defecto para el Frame es precisamente el BorderLayout, la indicación de separación entre Componentes no está incluida por defecto. Si se desea indicar esta separación, o gap, es necesario utilizar un controlador creado ex profeso, es decir, no se puede utilizar un objeto anónimo, sino uno con nombre para poder invocar el método que fija la separación entre Componentes. BorderLayout miLayout = new BorderLayout(); miLayout.setVgap( 30 ); miLayout.setHgap( 30 ); this.setLayout( miLayout ); Otro grupo de sentencias interesantes son las que permiten instancias el objeto Canvas de la clase MiCanvas, que extiende a la clase Canvas y lo incorpora a un objeto Frame en su posición central. El objeto MiCanvas no se puede instanciar como objeto anónimo, porque sobre él se va a registrar posteriormente un receptor de eventos del ratón. // Se instancia un objeto de MiCanvas MiCanvas miObjCanvas = new MiCanvas(); // Se añade el objeto MiCanvas creado al Centro del objeto // Frame a través del BorderLayout this.add( miObjCanvas,"Center" ); Las sentencias anteriores están seguidas de código ya muy utilizado a la hora de incorporar botones a un objeto Frame y hacer que se visualicen en pantalla. También está el código que registra el receptor de eventos de la ventana utilizado para concluir la aplicación cuando se cierra el Frame. Así que el siguiente trozo interesante es el fragmento de código que instancia y registra un objeto receptor de eventos que va a procesar los eventos del ratón, para determinar las coordenadas en que se encuentra el cursor en la pantalla, cuando el usuario pulsa el ratón. Este objeto Listener es instanciado anónimamente y no pasa referencia alguna del objeto MiCanvas al constructor del objeto Listener. Por lo tanto, el objeto receptor de eventos debe identificar el Componente sobre el cual ha de presentar la información de las coordenadas desde su propio código. Ya se verá que esta identificación la consigue basándose en el objeto MouseEvent que es pasar a este receptor cuando sucede un evento de este tipo. miObjCanvas.addMouseListener( new ProcRaton() ); Ya, para concluir la revisión del ejemplo, se encuentra el código que define la clase Listener que va a presentar las coordenadas del cursor sobre el mismo objeto sobre el cual se ha registrado. Esta versión utiliza el método getComponent() sobre el mismo objeto MouseEvent que le llega para identificar el Componente que ha originado en evento. Este método devuelve una referencia a un objeto de tipo Component, luego es necesario hacer un moldeo hacia el tipo MiCanvas antes de poder acceder a las variables de instancia que se han definido para la clase MiCanvas. class ProcRaton extends MouseAdapter { // Se sobrescribe el método mousePressed() para que haga lo que se ha // indicado public void mousePressed( MouseEvent evt ) { // Recoge las coordenadas x e y de la posición del cursor y las // almacena en variables de instancia del objeto MiCanvas. Es necesario // el casting para poder acceder a las variables de instancia ((MiCanvas)evt.getComponent()).posicionX = evt.getX(); ((MiCanvas)evt.getComponent()).posicionY = evt.getY(); // Se presentan las coordenadas en pantalla evt.getComponent().repaint(); } } El resto del código del programa ya está muy visto y no merece la pena el volver sobre él. Las barras de desplazamiento (Scrollbar) se utilizan para permitir realizar ajustes de valores lineales en pantalla, porporcionan una forma de trabajar con rangos de valores o de áreas, como en el caso de un área de texto en donde se proporcionan las barras de desplazamiento de forma automática. El ejemplo java1309.java es muy sencillo y solamente presenta en pantalla tres barras de desplazamiento que podrían utilizarse como selector para fijar un color, en base a sus componentes básicos de rojo, verde y azul. La apariencia en pantalla es la que muestra la figura. Y el código de este sencillo programa es el que se reproduce en las siguientes líneas. import java.awt.*; import java.awt.event.*; class java1309 extends Frame { public static void main( String args[] ) { // Se instancia un objeto del tipo de la clase new java1309(); } public java1309() { Scrollbar rojo,verde,azul; rojo = new Scrollbar( Scrollbar.VERTICAL,0,1,0,255 ); verde = new Scrollbar( Scrollbar.VERTICAL,0,1,0,255 ); azul = new Scrollbar( Scrollbar.VERTICAL,0,1,0,255 ); Frame miFrame = new Frame( "Tutorial de Java, AWT" ); miFrame.setLayout( new FlowLayout() ); // Se incorporan las tres barras de desplazamiento al objeto Frame miFrame.add( rojo ); miFrame.add( verde ); miFrame.add( azul ); // Se fija el tamaño del Frame y se hace que aparezca todo // en pantalla miFrame.setSize( 250,100 ); miFrame.setVisible( true ); // Se instancia y registra un objeto receptor de eventos de la // ventana para poder concluir la aplicación cuando el usuario // cierre el Frame Conclusion conclusion = new Conclusion(); miFrame.addWindowListener( conclusion ); } } // Concluye la ejecucion de la aplicacion cuando el usuario cierra la // ventana, porque se genera un evento windowClosing class Conclusion extends WindowAdapter { public void windowClosing( WindowEvent evt ) { System.exit( 0 ); } } Este tipo de interfaz proporciona al usuario un punto de referencia visual de un rango y al mismo tiempo la forma de cambiar los valores. Por ello, las barras de desplazamiento son Componentes un poco más complejos que los demás, reflejándose esta complejidad en sus constructores. Al crearlos hay que indicar su orientación, su valor inicial, los valores mínimo y máximo que puede alcanzar y el porcentaje de rango que estará visible. Si se utilizase una barra de desplazamiento para un rango de valores de color, tal como se hace en el ejemplo java1310.java, en el cual se crea una barra de desplazamiento horizontal y en donde el ancho de esa barra será mayor, en relación al Scrollbar. La imagen de la figura representa la captura de la ejecución inicial de la aplicación, modificada con las indicaciones explicativas de los valores. Tanto en este ejemplo como en el anterior, que son muy sencillos, no se controlan los eventos generados por la actuación del usuario sobre la barra. Esto ya se hizo en ejemplos anteriores, java1109.java. El código de este nuevo ejemplo, simplemente cambia la declaración e instanciación de las tres barras de desplazamiento del ejemplo java1309.java por una barra horizontal, de la forma: rango = new Scrollbar( Scrollbar.HORIZONTAL,0,64,0,255 ); En este caso, maxValue representa el valor máximo que va a alcanzar el lado izquierdo del indicador de la barra. Si se quieren representar 64 valores simultáneamente, es decir, de [0-63] a [192-255], maxValue debería ser 192. El lector habrá observado que las barras de desplazamiento no proporcionan información textual a usuario sobre el valor exacto que está seleccionado, o una zona donde poder mostrar directamente los valores asociados a los desplazamientos. Si se desea proporcionar esa información, se ha de proveer explícitamente una caja de texto u otro objeto similar donde presentar esa información, tal como se muestra en el ejemplo java1311.java, cuya imagen en ejecución es la que reproduce la figura siguiente. El código del ejemplo en este caso ya recoge los eventos originados en la barra de desplazamiento. Cada vez que se produce un desplazamiento del indicador de la barra, se genera un evento de tipo Ajuste, que es recogido por el receptor registrado sobre la barra, que a su vez se encarga de presentar el valor numérico correspondiente a la posición actual en el campo de texto utilizado como indicador auxiliar. Todo el ejemplo es una recopilación de la información proporcionada en los programas anteriores, y no merece la pena detenerse en ninguna de las sentencias que lo componen. |
|