0% encontró este documento útil (0 votos)
7 vistas

notasGUI

Cargado por

Antonio Montero
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
7 vistas

notasGUI

Cargado por

Antonio Montero
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 35

Interfaces Gráficas de Usuario con JAVA

Héctor Tejeda V

Febrero, 2010
2
Índice general

1. Introducción 5
1.1. Componentes, gestores de disposición y captura de eventos . . 6
1.2. AWT y Swing . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

2. Caso de estudio 9
2.1. Mostrando texto en un cuadro de diálogo . . . . . . . . . . . . 9
2.2. Ingresando texto en un cuadro de diálogo . . . . . . . . . . . . 10
2.2.1. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3. Creando dibujos simples . . . . . . . . . . . . . . . . . . . . . 12
2.3.1. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.4. Dibujando rectángulos y elipses . . . . . . . . . . . . . . . . . 16
2.4.1. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.5. Figuras Rellenas y Colores . . . . . . . . . . . . . . . . . . . . 19
2.5.1. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.6. Dibujo de Arcos . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.6.1. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.7. Usando objetos con gráficas . . . . . . . . . . . . . . . . . . . 25
2.7.1. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.8. Texto e imágenes con etiquetas . . . . . . . . . . . . . . . . . 30
2.8.1. Ejercicio . . . . . . . . . . . . . . . . . . . . . . . . . . 32
2.9. Dibujado con polimorfismo . . . . . . . . . . . . . . . . . . . . 32
2.9.1. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . 32

3
4 ÍNDICE GENERAL
Capı́tulo 1

Introducción

Se presenta en este material, ejemplos que no son considerados en un


curso introductorio de Java, ya que las aplicaciones que se revisan tienen
interfaces de usuario que utilizan exclusivamente texto. La razón por la cual
son usadas estas interfaces textuales no es, porque tengan una gran ventaja;
en realidad, la única ventaja que tienen es su facilidad para ser creadas.
Por lo general, en un curso introductorio de Java se pretende no distraer
mucho la atención del estudiante en las cuestiones importantes del desarrollo
de software; por lo que en general la mayorı́a de los cursos introductorios se
centran en cuestiones relacionadas con la estructura y la interacción de los
objetos, el diseño de clases y la calidad del código.
Las interfaces gráficas de usuario o GUI (Graphical User Interface) son
también construidas usando objetos que interactúan, pero cuentan con una
estructura muy especializada y es por lo anterior que se evita usarlas antes de
aprender la estructura de los objetos en términos más generales. Una vez que
se tienen las bases, se está preparado para dar una mirada a la construcción
de las GUI.
Las GUI completan las aplicaciones con una interfaz formada por venta-
nas, menús, botones y otros componentes gráficos, y hacen que la aplicación
tenga una apariencia más parecida a las aplicaciones tı́picas, que son usadas
por la mayorı́a de la gente que usa un sistema de cómputo.
Se debe observar el doble significado de la palabra interfaz. Las interfaces
de las que se abordan en este material no son las interfaces de las clases
ni la construcción interfaz de Java. Cuando se dice interfaces de usuario,
se refiere a la parte de una aplicación que está visible en la pantalla y que
permite que un usuario interactúe con ella.

5
6 CAPÍTULO 1. INTRODUCCIÓN

Una vez que se sabe cómo crear una GUI en Java, se pueden desarrollar
programas que tengan una mejor presentación visual.

1.1. Componentes, gestores de disposición y


captura de eventos
Para la creación de una GUI son varios los detalles que están involucrados.
En este material no se cubren todos los detalles de las distintas tareas que
se pueden hacer, sólo se discuten los principios generales y un buen número
de ejemplos.
En Java, toda la programación de una GUI se hace mediante el uso de
bibliotecas de clases estándares especializadas. Una vez que se han compren-
dido los principios se pueden encontrar todos los detalles necesarios en la
documentación de la biblioteca estándar.
Los principios que se necesitan revisar se pueden dividir en tres bloques:

1. Las clases de elementos que se pueden mostrar en la pantalla.

2. La forma como se pueden acomodar los elementos que se muestran en


la pantalla.

3. La forma como se debe responder a una entrada del usuario.

Se discuten los puntos anteriores mediante los términos componentes,


gestores de dispositivos y manejo de eventos respectivamente.
Los componentes son las partes individuales con las cuales se construye
una GUI. Ejemplos de estos son los botones, los menús, los elementos del
menú, las cajas de verificación, los deslizadores, los campos de texto, etc. La
biblioteca de Java contiene una cantidad de componentes diseñados para ser
usados inmediatamente y también es posible que el programador escriba sus
propios componentes. Es necesario que se aprenda cuáles son los componen-
tes importantes, cómo son creados y cómo hacer para que aparezcan en la
pantalla tal cual se desea verlos.
Los gestores de disposición son empleados en la ubicación de los compo-
nentes en la pantalla. Los sistemas de GUI más viejos y primitivos manejaban
coordenadas bidimensionales, donde el programador indicaba mediante un
par ordenado de valores, que expresaban un valor en pı́xeles, la posición del
componente además del alto y el ancho del mismo. En los sistemas de GUI
1.2. AWT Y SWING 7

más modernos, esta forma es muy simple, ya que se debe tener en cuenta las
distintas resoluciones de pantalla, las diferentes fuentes, las ventanas que los
usuarios pueden redimensionar, y otros aspectos que hacen difı́cil la distribu-
ción de los componentes. La solución es un esquema donde el programador
pueda indicar la disposición de los componentes en términos más generales.
Por ejemplo, se puede indicar que “este componente deberá estar debajo de
este otro” o que “este componente se estrechará cuando la ventana cambie
de tamaño pero este otro tendrá un tamaño constante”. Lo anterior se logra
usando los gestores de disposición.
El manejo de eventos se refiere a la técnica que se usa para responder
a las entradas del usuario. Una vez que los componentes han sido creado y
que han sido posicionados en la pantalla, es necesario asegurar de que ocurra
algo cuando el usuario presione un botón, por ejemplo. El modelo que usa la
biblioteca de Java para lograr lo anterior está basada en eventos: si un usuario
activa un componente, por ejemplo, por pulsar un botón o seleccionar un
elemento de un menú, el sistema generará un evento. Entonces, la aplicación
puede recibir una notificación del evento, mediante la invocación de uno de
sus métodos, y se puede llevar a cabo la acción adecuada.

1.2. AWT y Swing


Java tiene dos bibliotecas para la construcción de interfaces gráficas de
usuario. La más antigua, denominada AWT (Abstract Window Toolkit), fue
introducida con el primer sistema Java original; más tarde, se agregó una
mejor biblioteca denominada Swing.
Swing utiliza algunas de las clases de la biblioteca AWT, reemplaza algu-
nas de las clases de AWT con sus propias versiones y agrega clases nuevas.
En este material, se usará la biblioteca Swing, aunque se usarán algunas
de las clases de AWT que todavı́a son empleadas en los programas Swing.
Para el caso de que existan clases equivalentes en ambas bibliotecas, se usarán
las versiones de Swing.
Como existen clases equivalentes en AWT y en Swing, las versiones Swing
han sido identificadas mediante el agregado de la letra ((J)) al comienzo del
nombre de la clase. Por ejemplo, existen las clases de nombre Button y
JButton, Frame y JFrame, Menu y JMenu, etc. Las clases que comienzan con
((J)) son versiones Swing; y serán las únicas que se usarán.
8 CAPÍTULO 1. INTRODUCCIÓN
Capı́tulo 2

Caso de estudio

Este caso de estudio está diseñado para iniciar el aprendizaje de las poten-
tes capacidades de Java para crear GUIs. Se muestran diez secciones breves,
en donde cada sección introduce unos cuantos conceptos básicos y propor-
ciona ejemplos visuales gráficos. En las secciones subsecuentes, se emplean
conceptos de la programación orientada a objetos para crear aplicaciones que
dibujan una variedad de figuras.

2.1. Mostrando texto en un cuadro de diálo-


go
Muchas aplicaciones usan ventanas o cuadros de diálogo, también lla-
mados diálogos para mostrar la salida. Por ejemplo, los navegadores como
Firefox o Microsoft Internet Explorer muestran páginas web en su propia
ventana. Programas de correo electrónico permiten teclear y leer mensajes
en una ventana. Tı́picamente, los cuadros de diálogo son ventanas en las
cuales los programas muestran mensajes importantes a los usuarios. La cla-
se JOptionPane proporciona cuadros de diálogo empaquetados previamente
que permiten a los programas mostrar ventanas conteniendo ventanas —
tales ventanas son llamadas diálogos de mensaje. El código que se muestra a
continuación muestra la cadena Bienvenido a Java en tres renglones.

1 // Dialogo1.java
2 // Imprimiendo múltiples lı́neas en un cuadro de diálogo
3 import javax.swing.JOptionPane; // importar la clase JOptionPane
4

9
10 CAPÍTULO 2. CASO DE ESTUDIO

5 public class Dialogo1 {


6 public static void main( String args[] ) {
7 // Mostrar un cuadro de diálogo con un mensaje
8 JOptionPane.showMessageDialog( null, "Bienvenido\na\nJava" );
9 } // fin del main
10 } // fin del cuadro de diálogo

En la lı́nea 3 se indica que el programa usará la clase JOptionPane del pa-


quete javax.swing. Este paquete contiene varias clases que ayudan a crear la
GUI para las aplicaciones. Los componentes GUI facilitan la entrada de datos
para un usuario, y la presentación de datos al usuario. La lı́nea 8 llama al
métódo showMessageDialog para mostrar un cuadro de diálogo conteniendo
un mensaje. El método requiere dos argumentos. El primer argumento de-
termina el Frame al cual es asociado el diálogo, si es null se asocia con el
Frame por defecto. El segundo argumento es el String que será mostrado
en el diálogo.
El método showMessageDialog es un método estático de la clase JOptionPane.
Los métodos estáticos definen frecuentemente tareas usadas que no requieren
la creación explı́cita de un objeto. Por ejemplo, muchos programas muestran
cuadros de diálogo, y en vez de requerir que se cree código que haga la ta-
rea, los diseñadores de la clase JOptionPane declararon un método estático
que realiza la tarea del programador. Un método estático generalmente es
llamado usando el nombre de la clase seguido por un punto y el nombre del
método.

2.2. Ingresando texto en un cuadro de diálo-


go
La aplicación que se muestra enseguida usa otro cuadro de diálogo pre-
definido JOptionPane llamado diálogo de entrada, que permite al usuario
ingresar datos en el programa. El programa pide el nombre del usuario, y
responde con un mensaje de diálogo conteniendo un saludo y el nombre que
el usuario haya ingresado.
1 // NombreDialogo.java
2 // Entrada Básica con un cuadro de diálogo.
3
4 import javax.swing.JOptionPane;
5 public class NombreDialogo {
2.2. INGRESANDO TEXTO EN UN CUADRO DE DIÁLOGO 11

6
7 public static void main( String args[] ) {
8 // solicitar al usuario que ingrese un nombre
9 String nombre =
10 JOptionPane.showInputDialog( "¿Cuál es tu nombre?" );
11 // crear el mensaje
12 String mensaje = String.format(
13 "¡Bienvenido, %s, a la Programación con Java!", nombre );
14 // mostrar el mensaje de bienvenida al usuario
15 JOptionPane.showMessageDialog( null, mensaje );
16 } // fin de main
17 } // fin de la clase NombreDialogo

Las lı́neas 9–10 usan el método showInputDialog de JOptionPane para


mostrar un diálogo de entrada conteniendo un mensaje y un campo, conocido
como campo de texto, en el cual el usuario puede poner texto. El argumento
pasado al método es el mensaje que indica lo que el usuario deberá ingresar.
El usuario teclea carácteres en el campo de texto, y después pulsa el botón
Aceptar o también puede presionar la tecla Intro para mandar la cadena al
programa. El método showInputDialog devuelve un String conteniendo los
carácteres tecleados por el usuario. La cadena es almacenada en la variable
nombre. Si se presiona el botón Cancelar en el diálogo, el método regresa
null y el programa muestra la palabra “null” como el nombre.
Las lı́neas 12–13 usan el método estático format que devuelve un String
para regresar una cadena conteniendo el saludo con el nombre del usuario.
El método format es parecido al método System.out.printf, excepto que
format regresa la cadena formateada en vez de mostrarla. La lı́nea 14 muestra
el saludo en un mensaje de diálogo.

2.2.1. Ejercicios
1. Escribir un programa que use entradas y salidas con cuadros de diálogo
con los métodos de la clase JOptionPane para multiplicar dos números.
Como el método showInputDialog regrese un String, se deberá con-
vertir el String ingresado por el usuario a un tipo int para hacer el
cálculo. El método

Integer.parseInt( String s )

toma un argumento tipo String representando un entero y regresa el


valor como un tipo int. El método parseInt es un método estático de
12 CAPÍTULO 2. CASO DE ESTUDIO

la clase Integer del paquete java.lang.

2.3. Creando dibujos simples


Una de las caracterı́sticas de Java es el soporte de gráficos que permite
a los programadores visualmente resaltar sus aplicaciones. En esta sección
se muestra una de las capacidades gráficas de Java —dibujado de lı́neas.
También se cubre lo básico para la creación de una ventana para mostrar un
dibujo sobre la pantalla de la computadora.
Para dibujar en Java, se requiere entender el sistema de coordenadas, un
esquema para identificar cada punto en la pantalla. Por defecto, la esquina
superior izquierda de un componente GUI tiene coordenadas (0,0). Una par
coordenado está compuesto de un coordenada en x, en este caso la coordenada
horizontal, y una coordena en y, la coordenada vertical. La coordenada en x
es la localidad horizontal moviéndose de izquierda a derecha. La coordenada
en y es la localidad vertical moviéndose de arriba hacia abajo.
Las coordenadas indican donde el gráfico deberá ser mostrado en pantalla.
Las unidades de las coordenadas están medidas en pixeles. Un pixel es la
unidad más pequeña de resolución que despliega el monitor. El término pixel
viene de las palabras del inglés picture element.
La aplicación que se muestra a continuación sólo dibuja dos lı́neas. La cla-
se DibujaPanel realiza el dibujo actual, mientras la clase DibujaPanelPrueba
crea una ventana para mostrar el dibujo. En la clase DibujaPanel, las sen-
tencias import en las lı́neas 4–5 permiten usar la clase Graphics del paquete
java.awt, el cual proporciona varios métodos para dibujar texto y figuras
sobre la pantalla, y la clase JPanel del paquete javax.swing proporciona
una área sobre la cual se puede dibujar.

1 // Clase DibujaPanel.java
2 // Usando drawLine para conectar las esquinas de un panel.
3
4 import java.awt.Graphics;
5 import javax.swing.JPanel;
6
7 public class DibujaPanel extends JPanel {
8
9 // dibujar una X desde las esquinas del panel
10 public void paintComponent( Graphics g ) {
11
2.3. CREANDO DIBUJOS SIMPLES 13

12 // llamar a paintComponent para asegurar que el panel


13 // se muestra correctamente
14 super.paintComponent( g );
15 int ancho = getWidth(); // ancho total
16 int alto = getHeight(); // altura total
17
18 // dibujar una lı́nea desde la izquierda superior
19 // hasta la derecha inferior
20 g.drawLine( 0, 0, ancho, alto );
21
22 // dibujar una lı́nea desde la izquierda inferior
23 // hasta la derecha superior
24 g.drawLine( 0, alto, ancho, 0 );
25 } // fin del método paintComponent
26 } // fin de la clase DibujaPanel

En la lı́nea 7 se usa la palabra reservada extends para indicar que la


clase DibujaPanel es una mejora del tipo JPanel. Con extends se indica
una relación de herencia en la cual la clase DibujaPanel inicia con los miem-
bros existentes (datos y métodos) de la clase JPanel. La clase desde la cual
DibujaPanel hereda, JPanel, aparece a la derecha de la palabra extends.
En esta relación de herencia, JPanel es llamada la superclase y DibujaPanel
es llamada la subclase. Con lo anterior se obtiene que la clase DibujaPanel
tenga los atributos (datos) y comportamiento (métodos) de la clase JPanel
y además las nuevas caracterı́sticas que se agregan en la declaración de la
clase DibujaPanel —especı́ficamente, la habilidad para dibujar dos lı́neas a
lo largo de las diagonales del panel.
Cada JPanel, incluyendo DibujaPanel, tienen un método paintComponent,
lı́neas 10–25, el cual es llamado por el sistema automáticamente cada vez
que se necesita mostrar el JPanel. Este método deberá ser sobreescrito si se
desea dibujar algo en el panel. Este método es llamado cuando un JPanel es
mostrado por primera vez en la pantalla, cuando este es cubierto y después
descubierto por alguna ventana, y cuando la ventana es redimensionada. Este
método requiere un argumento, un objeto Graphics, que es proporcionado
por el sistema cuando se llama a paintComponent.
La primera sentencia en cada método paintComponent que sobreescriba
al método heredado deberá ser
super.paintComponent( g );
lo cual asegura que el panel es dibujado apropiadamente en la pantalla antes
de iniciar el dibujo. En las lı́neas 15 y 16 se llaman dos métodos que la
14 CAPÍTULO 2. CASO DE ESTUDIO

clase DibujaPanel hereda de la clase JPanel, en general, cualquier clase


que extienda a otra, podrá usar cualquier método que esté declarado en
la superclase que tenga al modificador public. Los métodos getWidth y
getHeight regresan el ancho y el alto del JPanel respectivamente, los cuales
son almacenados en las variables que están declaradas en las lı́neas 15 y 16.
En las lı́neas 20 y 24 se usa la referencia g del tipo Graphics para llamar al
método drawLine que dibujará las lı́neas. Los primeros dos argumentos, del
método drawLine, son las coordenadas de un extremo de la lı́nea, y los otros
dos son las coordenadas del otro extremo. Si se redimensiona la ventana las
lı́neas serán escaladas automáticamente, ya que los argumentos están basados
en el ancho y alto del panel. Redimensionando la ventana en esta aplicación
provoca que el sistema llame al método paintComponent para redibujar el
contenido de DibujaPanel.
Para mostrar DibujaPanel en la pantalla, se deberá colocar este dentro de
una ventana. Se puede crear una ventana con un objeto de la clase JFrame. En
DibujaPanelPrueba, que se muestra enseguida, la lı́nea 4 se importa la clase
JFrame del paquete javax.swing. En la lı́nea 11 en el método main de la cla-
se DibujaPanelPrueba se crea una instancia de la clase DibujaPanel, la cual
contendrá el dibujo, y la lı́nea 14 crea un nuevo JFrame que puede contener y
mostrar el panel. La lı́nea 17 llama al método setDefaultCloseOperation
con el argumento JFrame.EXIT ON CLOSE para indicar que la aplicación de-
berá terminar cuando el usuario cierre la ventana. La lı́nea 17 usa el método
add de la clase JFrame para poner el panel conteniendo el dibujo en el frame.
La lı́nea 19 pone el tamaño del frame, empleando el método size dándole
dos parámetros —el ancho del frame, y el alto. En la lı́nea 20 se muestra el
JFrame.

1 // DibujaPanelPrueba.java
2 // Aplicación para montar un DibujaPanel.
3
4 import javax.swing.JFrame;
5
6 public class DibujaPanelPrueba {
7
8 public static void main( String args[] ) {
9
10 // crear un panel que contenga el dibujo
11 DibujaPanel panel = new DibujaPanel();
12
13 // crear un nuevo frame para contener al panel
2.3. CREANDO DIBUJOS SIMPLES 15

14 JFrame aplicacion = new JFrame();


15
16 // indicar que al salir del frame se cierre la aplicación
17 aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
18 aplicacion.add( panel ); // agregar el panel al frame
19 aplicacion.setSize( 250, 250 ); // fijar el tama~
no del frame
20 aplicacion.setVisible( true ); // hacer visible el frame
21 } // fin de main
22 } // fin de la clase DibujaPanelPrueba

2.3.1. Ejercicios
1. Usando ciclos y sentencias de control dibujar lı́neas para obtener diseños
interesantes.

a) Crear un diseño que dibuje lı́neas desde la esquina superior izquier-


da, desplegándose en abanico hasta que cubran la mitad superior
izquierda del panel. Una aproximación es dividir el ancho y alto
en un número igual de pedazos (15 pedazos estarı́a bien). El pri-
mer extremo de una lı́nea siempre estará en la esquina superior
izquierda (0,0), El segundo extremo puede encontrarse iniciando
en la esquina inferior izquierda, luego moverse hacia arriba un pe-
dazo vertical y un pedazo horizontal a la derecha. Dibujar una
lı́nea entre los dos extremos. Continuarse moviendo el extremo,
arriba y a la derecha, hasta llegar a la esquina superior derecha.
La figura se deberá ajustar cuando se redimensione la ventana.
b) Modificiar el programa del ejercicio anterior para desplegar lı́neas
desde las cuatro esquinas. Las lı́neas de las esquinas opuestas se
deberán intersectar.

2. Realizar los siguientes programas.

a) Crear un diseño iniciando con la división de cada lado del panel


en la misma cantidad de partes, se puede escoger 15. La primera
lı́nea inicia en la esquina superior izquierda y termina una parte
a la derecha sobre el lado inferior. Para las siguientes lı́neas, se
deberá mover hacia abajo en una parte del lado izquierdo, y una
parte hacia la derecha en el lado inferior. Repetir lo anterior hasta
que se alcance en el lado inferior la esquina inferior derecha.
16 CAPÍTULO 2. CASO DE ESTUDIO

b) Modificar el programa del ejercicio anterior para espejear el diseño


en las cuatro esquinas.

2.4. Dibujando rectángulos y elipses


En esta sección se muestra como dibujar rectángulos y elipses, usando de
la clase Graphics los métodos drawRect y drawOval respectivamente.
1 // Figuras.java
2 // Se muestran diferentes figuras que pueden ser dibujadas
3 import java.awt.Graphics;
4 import javax.swing.JPanel;
5
6 public class Figuras extends JPanel {
7 private int opcion; // opción del usuario de la figura a dibujar
8
9 // El constructor pone la opción del usuario
10 public Figuras( int opcionUsuario ) {
11 opcion = opcionUsuario;
12 } // fin del constructor Figuras
13
14 // dibujar una cascada de figuras iniciando desde la esquina
15 // superior izquierda
16 public void paintComponent( Graphics g ) {
17 super.paintComponent( g );
18 for ( int i = 0; i < 10; i++ ) {
19 // selecionar la figura basandose en la opción del usuario
20 switch ( opcion ) {
21 case 1: // dibujar rectángulos pasando las coordenadas del
22 // rectángulo dado por la esquina x, y, con ancho y alt o
23 g.drawRect( 10 + i * 10, 10 + i * 10,
24 50 + i * 10, 50 + i * 10 );
25 break;
26 case 2: // dibujar elipses
27 g.drawOval( 10 + i * 10, 10 + i * 10,
28 50 + i * 10, 50 + i * 10 );
29 break;
30 } // fin del switch
31 } // fin del for
32 } // fin del método paintComponent
33 } // fin de la clase Figuras

La lı́nea 6 inicia con la declaración de la clase Figuras, la cual extiende


a la clase JPanel. La variable de instancia, opcion, declarada en la lı́nea 7,
2.4. DIBUJANDO RECTÁNGULOS Y ELIPSES 17

determina si el método paintComponent deberá dibujar rectángulos o elipses.


El constructor en las lı́neas 10–12 inicializa opción con el valor pasado en el
parámetro opcionUsuario.
El método paintComponent, de las lı́neas 16–32, hace el dibujo. No se
debe olvidar que la primera sentencia que deberá ser llamada en este método
es super.paintComponent, como aparece en la lı́nea 19. Entre las lı́neas 18–
31 se tiene un ciclo que dibuja 10 figuras. La sentencia switch, lı́neas 20–30,
selecciona entre dibujar rectángulos y elipses.
Si opcion tiene 1, entonces el programa dibuja un rectángulo, mediante
la llamada al método drawRect de la clase Graphics en las lı́neas 23–24.
Este método requiere cuatro argumentos, siendo los dos primeros las coor-
denadas de la esquina superior izquierda del rectángulo, y los siguientes dos
parámetros representan el ancho y el alto del rectángulo. En este ejemplo se
inicia en una posición 10 pixeles abajo y 10 pixeles a la derecha de la esquina
superior izquierda, y en cada iteración del ciclo se mueve la esquina superior
izquierda otros 10 pixeles hacia abajo y a la derecha. El ancho y la altura
del rectángulo inician en 50 pixeles y se incrementan en 10 pixeles en cada
iteración.
Si opcion tiene 2, el programa dibuja una elipse. Cuando se dibuja una
elipse, se encuentra contenida en un rectángulo, bounding rectangle, y la elipse
toca los cuatro puntos medios del rectángulo. El método drawOval, lı́neas
27–28, requiere los mismos cuatro argumentos que el método drawRect. Los
argumentos especifican la posición y el tamaño del rectángulo que acota a
la elipse. Para este caso son los mismos valores que fueron dados para el
rectángulo.
Se muestra enseguida el programa que es el responsable para manejar la
entrada del usuario y crear una ventana para desplegar los dibujos apropiados
usando la selección del usuario.

1 // ProbarFiguras.java
2 // Aplicación de prueba que muestra la clase Figuras
3
4 import javax.swing.JFrame;
5 import javax.swing.JOptionPane;
6
7 public class ProbarFiguras {
8
9 public static void main( String args[] ) {
10 // obtener la opción del usuario
11 String entrada = JOptionPane.showInputDialog(
18 CAPÍTULO 2. CASO DE ESTUDIO

12 "Ingresar 1 para dibujar rectángulos\n" +


13 "Ingresar 2 para dibujar ovalos" );
14 // convertir la entrada a int
15 int opcion = Integer.parseInt( entrada );
16 // crear el panel con la entrada del usuario
17 Figuras panel = new Figuras( opcion );
18 JFrame application = new JFrame(); // crear a nuevo JFrame
19 application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
20 application.add( panel ); // agregar el panel al frame
21 application.setSize( 300, 300 ); // fijar el tama~
no deseado
22 application.setVisible( true ); // mostrar el frame
23 } // fin de main
24 } // fin de la clase ProbarFiguras

En las lı́neas 11–13 se pide al usuario, con un cuadro de diálogo de entrada,


que seleccione el tipo de figuras a dibujar; la respuesta es almacenada en la
variable entrada. En la lı́nea 15 se emplea el método parseInt de la clase
Integer para convertir el String guardado en la variable entrada a un tipo
int y se asigna a la variable opcion. Una instancia de la clase Figuras es
creada en la lı́nea 17, pasando la opción del usuario al constructor. Las lı́neas
17–22 realizan las operaciones habituales para crear y configurar la ventana
—crear un frame, configurar salir cuando la aplicación sea cerrada, agregar
el dibujo al frame, configurar el tamaño del frame y hacerlo visible.

2.4.1. Ejercicios
1. Dibujar 12 cı́rculos concéntricos en el centro de un JPanel. El cı́rculo
más interno deberá tener un radio de 10 pixeles, y cada cı́rculo sucesivo
deberá tener un radio de 10 pixeles más grande que el previo anterior.
Iniciar encontrando el centro del JPanel. Para obtener la esquina su-
perior izquierda de un cı́rculo moverse un radio hacia arriba y un radio
hacia la izquierda desde el centro. El ancho y el alto del rectángulo
acotador es el diámetro del cı́rculo (dos veces el radio).

2. Crear un programa que lea la entrada de varios valores, usando cua-


dros de diálogo, para mostrar una gráfica de barras con rectángulos, de
acuerdo a los valores dados.
2.5. FIGURAS RELLENAS Y COLORES 19

2.5. Figuras Rellenas y Colores


Se pueden crear muchos diseños interesantes con sólo lı́neas y figuras bási-
cas, la clase Graphics proporciona muchas más capacidades. Se revisarán a
continuación las caracterı́sticas de colores y figuras rellenas. Agregando color
se agrega otra caracterı́stica a los dibujos que el usuario ve en la computado-
ra. Las figuras rellenas cubren totalmente regiones con colores sólidos, en vez
de sólo dibujar los contornos.
Los colores mostrados en las pantallas de las computadoras están defini-
dos por sus partes de rojo, verde y azul. Estas partes, conocidos como valores
RGB (Red Green Blue), tiene valores enteros entre 0 y 255. Entre más gran-
de sea el valor, mayor tinte tendrá el color final. Java emplea la clase Color
del paquete java.awt para representar colores usando sus valores RGB. La
clase Color en el paquete java.awt es empleada por Java para representar
colores usando los valores RGB. La clase Color contiene 13 objetos predefini-
dos estáticos — Color.BLACK, Color.BLUE, Color.CYAN, Color.DARK GRAY,
Color.GRAY, Color.GREEN, Color.LIGHT GRAY, Color.MAGENTA, Color.ORAN-
GE, Color.PINK, Color.RED, Color.WHITE y Color.YELLOW. La clase Color
también contiene un constructor de la forma:

public Color( int r, int g, int b)

para que se puedan crear colores hechos a la medida especificando los com-
ponentes individuales rojo, verde y azul de un color.
Los rectángulos y las elipses rellenas son dibujados con los métodos fillRect
y fillOval de la clase Graphics, respectivamente. Estos dos métodos tie-
nen los mismos parámetros como sus contrapartes sin rillenar drawRect y
drawOval; los primeros dos parámetros son las coordenadas para la esquina
superior izquierda de la figura, mientras los siguientes dos parámetros deter-
minan su ancho y alto. El código de enseguida crea una cara sonriente, ver
figura 2.1, empleando colores y figuras rellenas.

1 // CaraSonriente.java
2 // Muestra figuras rellenas
3
4 import java.awt.Color;
5 import java.awt.Graphics;
6 import javax.swing.JPanel;
7
8 class CaraSonriente extends JPanel {
20 CAPÍTULO 2. CASO DE ESTUDIO

Figura 2.1: Una cara sonriente empleando fillOval y la clase


java.awt.Color

9
10 public void paintComponent( Graphics g ) {
11 super.paintComponent( g );
12 // dibujar la cara
13 g.setColor( Color.YELLOW );
14 g.fillOval( 10, 10, 200, 200 );
15 // draw los ojos
16 g.setColor( Color.BLACK );
17 g.fillOval( 55, 65, 30, 30 );
18 g.fillOval( 135, 65, 30, 30 );
19 // dibujar la boca
20 g.fillOval( 50, 110, 120, 60 );
21 // "retocar" la boca en una sonrisa
22 g.setColor( Color.YELLOW );
23 g.fillRect( 50, 110, 120, 30 );
24 g.fillOval( 50, 120, 120, 40 );
25 } // fin del método paintComponent
26 } // fin de CaraSonriente

Las sentencias import en las lı́neas 4–6 del código anterior importan las
clases Color, Graphics y JPanel. La clase CaraSonriente, lı́neas 10–25, usa
la clase Color para especificar los colores de dibujo, y usa la clase Graphics
para dibujar. La clase JPanel proporciona el área en la cual se dibujará. En
la lı́nea 13 se emplea setColor de la clase Graphics para indicar el color
con el que se dibujará usando el color amarillo. El método setColor requiere
un argumento, el color que será puesto como el color para dibujar. La lı́nea
14 dibuja un cı́rculo con diámetro 200 para representar la cara. En la lı́nea
16 se pone el color negro, y las lı́neas 17 y 18 ponen los ojos. La boca se
dibuja con una elipse en la lı́nea 20, pero no tiene el diseño requerido. Para
2.5. FIGURAS RELLENAS Y COLORES 21

formar la sonrisa en la boca, se retoca la boca. En la lı́nea 22 se pone el color


amarillo y en la lı́nea 23 se dibuja un rectángulo que tiene la mitad de altura
de la boca, con lo que se borra la mitad superior de la boca, quedando solo
la mitad inferior visible. Para crear una mejor sonrisa la lı́nea 24 dibuja otra
elipse para cubrir ligeramente la parte superior de la boca.

1 // PruebaCaraSonriente
2 // Probar aplicación que muestra cara sonriente
3
4 import javax.swing.JFrame;
5
6 public class PruebaCaraSonriente {
7
8 public static void main( String args[] ) {
9 CaraSonriente panel = new CaraSonriente();
10 JFrame aplicacion = new JFrame();
11 aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
12 aplicacion.add( panel );
13 aplicacion.setSize( 230, 250 );
14 aplicacion.setVisible( true );
15 } // fin de main
16 } // fin de la clase PruebaCaraSonriente

La clase PruebaCaraSonriente, código de arriba, crea y muestra un


JFrame conteniendo el dibujo. Cuando el JFrame es mostrado, el sistema
llama al método paintComponent para dibujar la cara sonriente.

2.5.1. Ejercicios
1. Usando el método fillOval, dibujar una diana que alterne entre dos
colores aleatorios. Usar el constructor Color( int r, int g, int b)
con argumentos aleatorios para generar colores aleatorios.

2. Crear un programa que dibuje 10 figuras rellenas aleatorias en colo-


res, posiciones y tamaños aleatorios. El método paintComponent de-
berá contener un ciclo que itere 10 veces. En cada iteración, el ciclo
deberá determinar si dibuja un rectángulo relleno o una elipse, crear
un color aleatorio y escoger coordenadas y dimensiones aleatorias. Las
coordenadas deberán escogerse basadas en el ancho y alto del panel.
Longitudes de los lados deberán limitarse a la mitad del ancho y alto
de la ventana.
22 CAPÍTULO 2. CASO DE ESTUDIO

2.6. Dibujo de Arcos


Usando las caracterı́sticas gráficas de Java, se pueden crear dibujos más
complejos que serı́an más tediosos codificar lı́nea por lı́nea. En el siguiente
código se emplean arreglos y sentencias de repetición para dibujar un arco iris,
ver figura 2.2, usando el método fillArc de la clase Graphics. El dibujado de
arcos es similar al dibujado de elipses —un arco es simplemente una sección
de una elipse.

Figura 2.2: Dibujo de un arco iris empleando drawArc

1 // DibujaArcorIris.java
2 // Se muestra el uso de colores en un arreglo.
3 import java.awt.Color;
4 import java.awt.Graphics;
5 import javax.swing.JPanel;
6
7 class DibujaArcoIris extends JPanel {
8
9 // Definir el color ı́ndigo y violeta
10 final Color VIOLETA = new Color( 128, 0, 128 );
11 final Color INDIGO = new Color( 75, 0, 130 );
12
13 // Colores para el arco iris, iniciando con el mas interno.
14 // Las dos entradas en blanco dan un arco vacı́o en el centro
15 private Color colores[] = {
16 Color.WHITE, Color.WHITE, VIOLETA, INDIGO, Color.BLUE,
17 Color.GREEN, Color.YELLOW, Color.ORANGE, Color.RED
18 };
19
20 // constructor
21 public DibujaArcoIris() {
2.6. DIBUJO DE ARCOS 23

22 setBackground( Color.WHITE ); // fijar el fondo a blanco


23 } // fin del constructor DibujaArcoIris
24
25 // dibujar un arco iris usando cı́rculos concéntricos
26 public void paintComponent( Graphics g ) {
27 super.paintComponent( g );
28
29 int radio = 20; // radio de un arco
30
31 // dibujar el arco iris en la parte inferior y al centro
32 int centroX = getWidth() / 2;
33 int centroY = getHeight() - 10;
34
35 // dibujar arcos rellenos iniciando con el más exterior
36 for ( int i = colores.length; i > 0; i-- ) {
37 // fijar el color para el arco actual
38 g.setColor( colores[ i - 1 ] );
39
40 // fijar el arco desde 0 a 180 grados
41 g.fillArc( centroX - i * radio, centroY - i * radio,
42 i * radio * 2, i * radio * 2, 0, 180 );
43 } // fin del for
44 } // fin del método paintComponent
45 } // fin de la clase DibujaArcoIris

El código anterior inicia con las sentencias import usuales para crear los
dı́bujos, lı́neas 3–5. Las lı́neas 10–11 declaran y crean dos nuevos colores
–VIOLETA e INDIGO. Para los colores del arco iris en la clase Color se en-
cuentran definidos los primeros 5 de los 7 colores del arco iris. En las lı́neas
15–17 se inicializa un arreglo con los colores del arco iris, iniciando primero
con los arcos más internos. El arreglo inicia con dos elementos Color.WHITE,
los cuales son para dibujar los arcos vacı́os en el centro del arco iris. El cons-
tructor de las lı́neas 21–23 contiene una sola sentencia que llama al método
setBackground, el cual se hereda desde la clase JPanel, con el parámetro
Color.White. El método setBackground toma un solo argumento tipo Color
y fija el fondo del componente a ese color.
En la lı́nea 29 se declara la variable local radio, la cual determina el
radio de cada arco. Las variables locales centroX y centroY, lı́neas 32–33,
determinan la localidad del punto medio en la base de la ventana. El ciclo en
las lı́neas 36–43 usa la variable de control i para contar hacia atrás a partir
del final del arreglo, dibujando los arcos más grandes primero y colocando
arcos más pequeños sucesivante al frente del previo. En la lı́nea 38 se fija el
24 CAPÍTULO 2. CASO DE ESTUDIO

color para dibujar el arco actual desde el arreglo.


El método fillArc usado en las lı́neas 41–42 dibuja un semicı́rculo lleno.
Este método requiere seis parámetros. Los primeros cuatro representan el
rectángulo acotador en el cual el arco será dibujado. Los primeros dos de
estos indican las coordenadas de la esquina superior izquierda del rectángulo
acotador, y los siguientes dos indican el ancho y alto. El quinto parámetro
es el ángulo inicial en la elipse, y el sexto indica el barrido, o la cantidad de
arco a cubrir. El ángulo inicial y de barrido están medidos en grados, con
cero grados apuntando a la derecha. Un barrido positivo dibuja el arco en
sentido contrario a las manecillas, mientras uno negativo dibuja en el sentido
de las manecillas. Un método similar a fillArc es drawArc —este requiere
los mismos parámetros como fillArc, pero dibuja la arista del arco en vez
de llenarlo.

1 // PruebaDibujaArcoIris.java
2 // Aplicación de prueba para mostrar un arco iris.
3
4 import javax.swing.JFrame;
5
6 public class PruebaDibujaArcoIris {
7
8 public static void main( String args[] ) {
9 DibujaArcoIris panel = new DibujaArcoIris();
10 JFrame aplicacion = new JFrame();
11 aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
12 aplicacion.add( panel );
13 aplicacion.setSize( 400, 250 );
14 aplicacion.setVisible( true );
15 } // fin del main
16 } // fin de la clase PruebaDibujaArcoIris

La clase PruebaDibujaArcoIris, código anterior, crea y configura un


JFrame para mostrar el arco iris. Una vez que el programa hace al panel visi-
ble, el sistema llama al método paintComponent de la clase DibujaArcoIris
para dibujar el arco iris en la pantalla.

2.6.1. Ejercicios
1. En el ejercicio, se dibujarán espirales, ver figura 2.3, con los métodos
drawLine y drawArc. Las espirales deberán cubrir todo el panel, no
debe haber zonas sin llenar al redimensionar la ventana.
2.7. USANDO OBJETOS CON GRÁFICAS 25

a) Dibujar una espiral cuadrada centrada en el panel, usando el méto-


do drawLine. Una técnica es usar un ciclo que incremente la lon-
gitud de la lı́nea después de dibujar la segunda lı́nea. La dirección
para dibujar la siguiente linea deberá seguir un patrón, como aba-
jo, izquierda, arriba, derecha.
b) Dibujar una espiral circular usando el método drawArc para dibu-
jar un semicı́rculo cada vez. Cada semicı́rculo sucesivo deberá te-
ner un radio mayor y deberá continuar dibujando donde el se-
micı́rculo previo termino.

Figura 2.3: Dibujo de espirales usando drawLine y drawArc

2.7. Usando objetos con gráficas


Los ejemplos que se han revisado hasta ahora no varı́an cada vez que se
ejecuta el programa. Sin embargo, en el segundo ejercicio de la subsección
2.5.1 se pide crear un programa que genera figuras y colores de manera alea-
toria. En aquel ejercicio, el dibujo cambia cada vez que el sistema llama a
paintComponent para redibujar la pantalla. Para crear un dibujo más con-
sistente que permanezca igual cada vez que es dibujado, se debe guardar la
información acerca de las figuras mostradas para que se puedan reproducir
de forma exacta cada vez que el sistema llame a paintComponent.
26 CAPÍTULO 2. CASO DE ESTUDIO

Para realizar lo anterior, se creará un conjunto de clases de figuras que


guardarán información acerca de cada figura. Se harán estas clases “inteli-
gentes” permitiendo que objetos de estas clases dibujarse a si mismo si se
proporciona un objeto Graphics. En el código que aparace enseguida, la clase
MiLinea tiene todas las capacidades indicadas.
La clase MiLinea importa las clases Color y Graphics en las lı́neas 3–4.
Las lı́neas 8–12 declaran variables de instancia para las coordenadas nece-
sarias para dibujar una lı́nea, y la lı́nea 12 declara la variable de instancia
que guarda el color de la lı́nea. El constructor en las lı́neas 15–21 toma cinco
parámetros, uno para cada variable de instancia que se inicializará. El méto-
do dibujar en las lı́neas 24–27 necesita un objeto Graphics que es usado
para dibujar la lı́nea en el color y las coordenadas apropiadas.
1 // MiLinea.java
2 // Declaración de la clase MiLinea
3 import java.awt.Color;
4 import java.awt.Graphics;
5
6 public class MiLinea {
7
8 private int x1; // coordenada en x del primer extremo
9 private int y1; // coordenada en y del primer extremo
10 private int x2; // coordenada en x del segundo extremo
11 private int y2; // coordenada en y del segundo extremo
12 private Color miColor; // color de esta figura
13
14 // constructor con valores de entradas
15 public MiLinea( int x1, int y1, int x2, int y2, Color color ) {
16 this.x1 = x1; // poner el valor en x del primer extremo
17 this.y1 = y1; // poner el valor en y del primer extremo
18 this.x2 = x2; // poner el valor en x del segundo extremo
19 this.y2 = y2; // poner el valor en y del segundo extremo
20 miColor = color; // poner el color
21 } // fin del constructor MiLinea
22
23 // Dibujar la lı́nea en el color indicado
24 public void dibujar( Graphics g ) {
25 g.setColor( miColor );
26 g.drawLine( x1, y1, x2, y2 );
27 } // fin del método dibujar
28 } // fin de la clase MiLinea

A continuación se declara la clase DibujaPanel.java, la cual generará ob-


jetos aleatorios de la clase MiLinea. La lı́nea 11 declara un arreglo MiLinea
2.7. USANDO OBJETOS CON GRÁFICAS 27

para guardar las lı́neas a dibujar. Dentro del constructor, lı́neas 14–35, en la
lı́nea 15 se fija el color del fondo a Color.WHITE. La lı́nea 17 crea el arreglo
con una longitud aleatoria entre 5 y 9. El ciclo, en las lı́neas 20–34 crea un
nuevo MiLinea para cada elemento en el arreglo. Las lı́neas 22–25 generan
coordenadas aleatorias para cada los extremos de cada lı́nea, en las lı́neas
28–30 se genera un color aleatorio para la lı́nea. En la lı́nea 33 se crea un
nuevo objeto MiLinea con los valores generados aleatoriamente y se guarda
este en el arreglo.
El método paintComponent itera con los objetos MiLinea en el arre-
glo lineas usando una versión mejorada del ciclo for, lı́neas 41–42. Cada
iteración llama el método dibujar del objeto actual MiLinea y le pasa el ob-
jeto Graphics para dibujarlo en el panel. La clase PruebaDibujo, siguiente
código, configura una nueva ventana para mostrar el dibujo. Como se están
fijando las coordenadas para las lı́neas solamente una vez en el constructor,
el dibujo no cambia si paintComponent es llamado para refrescar el dibujado
en la pantalla.

1 // DibujaPanel.java
2 // Programa que usa la clase MiLinea
3 // para dibujar lı́neas aleatorias
4 import java.awt.Color;
5 import java.awt.Graphics;
6 import java.util.Random;
7 import javax.swing.JPanel;
8
9 public class DibujaPanel extends JPanel {
10 private Random numerosAleatorios = new Random();
11 private MiLinea lineas[]; // arreglo de lı́neas
12
13 // constructor, crea un panel con figuras aleatorias
14 public DibujaPanel() {
15 setBackground( Color.WHITE );
16
17 lineas = new MiLinea[ 5 + numerosAleatorios.nextInt( 5 ) ];
18
19 // crear lı́neas
20 for ( int i = 0; i < lineas.length; i++ ) {
21 // generar números aleatorios
22 int x1 = numerosAleatorios.nextInt( 300 );
23 int y1 = numerosAleatorios.nextInt( 300 );
24 int x2 = numerosAleatorios.nextInt( 300 );
25 int y2 = numerosAleatorios.nextInt( 300 );
28 CAPÍTULO 2. CASO DE ESTUDIO

26
27 // generar un color aleatorio
28 Color color = new Color( numerosAleatorios.nextInt( 256 ),
29 numerosAleatorios.nextInt( 256 ),
30 numerosAleatorios.nextInt( 256 ) );
31
32 // agregrar la lı́nea a la lista de lı́neas que serán mostradas.
33 lineas[ i ] = new MiLinea( x1, y1, x2, y2, color );
34 } // fin del for
35 } // fin del constructor DrawPanel
36
37 // para cada figura del arreglo, dibujar las figuras individuales
38 public void paintComponent( Graphics g ) {
39 super.paintComponent( g );
40 // dibujar las lı́neas
41 for ( MiLinea linea : lineas )
42 linea.dibujar( g );
43 } // fin del método paintComponent
44 } // fin de la clase DibujaPanel

1 // PruebaDibuja.java
2 // Aplicación de prueba para mostrar un DibujaPanel.
3
4 import javax.swing.JFrame;
5
6 public class PruebaDibujo {
7
8 public static void main( String args[] ) {
9
10 DibujaPanel panel = new DibujaPanel();
11 JFrame application = new JFrame();
12
13 application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
14 application.add( panel );
15 application.setSize( 300, 300 );
16 application.setVisible( true );
17 } // fin de main
18 } // fin de la clase PruebaDibujo

2.7.1. Ejercicios
1. Extender el programa de esta sección para dibujar aleatoriamente rectángu-
los y elipses. Crear las clases MiRectangulo y MiElipse. Ambas clases
deberán incluir coordenadas x1, y1, x2, y2, un color y un valor boo-
2.7. USANDO OBJETOS CON GRÁFICAS 29

leano para determinar si la figura es rellena. Declarar un constructor


en cada clase con argumentos para inicializar todas las variables de
instancia. Para ayudar a dibujar rectángulos y elipses, cada clase de-
berá dar métodos getSuperiorIzquierdaX, getSuperiorIzquierdaY,
getAncho y getAlto que calculen la coordenada superior izquierda x,
la coordenada superior izquierda y, el ancho y el alto, respectivamen-
te. La coordenada superior izquierda x, es el valor más pequeño de las
dos coordenadas x, de manera similar para la coordenada superior y,
el ancho es el valor absoluto de la diferencia entre las abscisas, y la
altura es el valor absoluto de la diferencia entre las dos ordenadas de
los extremos.

La clase DibujaPanel, la cual extiende a JPanel, maneja la creación


de las figuras, deberá declarar tres arreglos, uno para cada forma de
figura. La longitud de cada arreglo deberá ser un número aleatorio entre
1 y 5. El constructor de la clase DibujaPanel llenará cada uno de los
arreglos con figuras de posición, tamaño, color y llenado aleatorio, como
se indica en el ejercicio 2 de la sección 2.5.1.

Adicionalmente, modificar las tres clases de figuras para incluir lo si-


guiente:

a) Un constructor sin argumentos que fija todas las coordenadas de


la figura a cero, el color de la figura a color negro, y la propiedad de
llenado a false, esto último sólo para MiRectangulo y MiElipse.

b) Métodos set para las variables de instancia en cada clase. Los


métodos que fijen un valor coordenado deberán verificar que el
argumento es mayor que, o igual a cero antes de fijar la coordenada
— si no, estos deberán poner la coordenada a cero. El constructor
deberá llamar a los métodos set en vez de inicializar las variables
de instancia directamente.

c) Métodos get para las variables de instancia en cada clase. El méto-


do dibujar deberá referenciar las coordenadas por los métodos get
en vez de acceder directamente a las variables.
30 CAPÍTULO 2. CASO DE ESTUDIO

2.8. Texto e imágenes con etiquetas


Los programas frecuentemente usan etiquetas cuando requieren mostrar
información o instrucciones al usuario en una interfaz gráfica. Las etiquetas
son una forma conveniente para identificar componentes GUI en la pantalla
y para mantener informado al usuario respecto al estado actual del progra-
ma. En Java, un objeto de la clase JLabel del paquete javax.swing puede
mostrar una sola lı́nea de texto, una imagen o ambos. El siguiente ejemplo
muestra varias caracterı́sticas de JLabel.

1 // LabelDemo.java
2 // Muestra el uso de etiquetas
3 import java.awt.BorderLayout;
4 import javax.swing.ImageIcon;
5 import javax.swing.JLabel;
6 import javax.swing.JFrame;
7
8 public class LabelDemo {
9
10 public static void main( String args[] ) {
11 // crear una etiqueta plana con texto
12 JLabel etiquetaNorte = new JLabel( "Norte" );
13
14 // crear un icono desde una imagen para ponerlo en un JLabel
15 ImageIcon iconoEtiqueta = new ImageIcon( "gnome-gnibbles.png" );
16
17 // crear una etiqueta con un icono en vez de texto
18 JLabel etiquetaCentro = new JLabel( iconoEtiqueta );
19
20 // crear otra etiqueta con un icono
21 JLabel etiquetaSur = new JLabel( iconoEtiqueta );
22
23 // configurar etiqueta para mostrar texto, al igual que el icono
24 etiquetaSur.setText( "Sur" );
25
26 // crear una ventana para poner las etiquetas
27 JFrame aplicacion = new JFrame();
28
29 aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
30
31 // agregar las etiquetas a la ventana, el segundo argumento indica
32 // en que lugar de la ventana se pondra la etiqueta
33 aplicacion.add( etiquetaNorte, BorderLayout.NORTH );
34 aplicacion.add( etiquetaCentro, BorderLayout.CENTER );
2.8. TEXTO E IMÁGENES CON ETIQUETAS 31

35 aplicacion.add( etiquetaSur, BorderLayout.SOUTH );


36
37 aplicacion.setSize( 300, 300 ); // fijar el tama~
no de la ventana
38 aplicacion.setVisible( true ); // mostrar la ventana
39 } // fin de main
40 } // fin de la clase LabelDemo

En las lı́neas 3–6 se importan las clases que se requieren para mostrar las
etiquetas. BorderLayout del paquete java.awt tiene constantes para indicar
donde se pueden colocar componentes GUI en un JFrame. La clase ImageIcon
representa una imagen que puede ser mostrada en un JLabel, y la clase
JFrame representa la ventana que contendrá todas las etiquetas.
La lı́nea 12 crea un JLabel que muestra su argumento para el constructor
—la cadena "Norte". La lı́nea 15 declara la variable local iconoEtiqueta
y le asigna un nuevo ImageIcon. El constructor para ImageIcon recibe una
cadena que indica el camino a la imagen. Como solamente se indica un nom-
bre de archivo, Java supone se encuentra en el mismo directorio de la cla-
se LabelDemo. ImageIcon puede cargar imágenes en formato GIF, JPEG y
PNG. La lı́ena 18 declara e inicializa la variable local etiquetaCentro con
un JLabel que muestra a iconoEtiqueta. Sin embargo, en la lı́nea 24 se
llama al método setText para cambiar el texto que la etiqueta muestra. El
método setText puede ser llamado por cualquier JLabel para cambiar su
texto. Este JLabel mostrará el icono y el texto.
En la lı́nea 27 se crea un JFrame que mostrará los JLabels, y la lı́nea
29 indica que el programa deberá terminar cuando el JFrame se cierre. Se
ponene las etiquetas en la ventana en las lı́neas 33–35 llamando una versión
sobrecargada del método add que toma dos parámetros. El primer método es
el componente que se quiere poner, y el segundo es la región en la cual este
deberá ser puesto. Cada JFrame tiene asociado un manejador que ayuda en
la posición de los componentes que tiene puestos. El manejado por defecto
para un JFrame es el conocido como BorderLayout y tiene cinco regiones —
NORTH (superior), SOUTH (inferior), EAST (lado derecho), WEST (lado izquierdo)
y CENTER (centro). Cada uno de estos está declarado como una constante en
la clase BorderLayout. Cuando se llama al método add con un argumento,
el JFrame coloca al componente usando CENTER automáticamente. Si una
posición ya contenı́a un componente, entonces el nuevo componente toma su
lugar. En las lı́neas 27 y 39 se pone el tamaño de la ventana y se hace visible
en pantalla.
32 CAPÍTULO 2. CASO DE ESTUDIO

2.8.1. Ejercicio
1. Modificar el ejercicio 1 de la sección 2.7.1 para incluir un JLabel como
una barra de estado que muestre la cantidad de cada figura dibujada,
podrı́a tener un texto como: ”Lı́neas 3, Elipses 2, Rectángulos 4 ”. La
clase DibujaPanel deberá declarar un método que regrese una cadena
conteniendo el texto del estado. En el método main, primero crear el
DibujaPanel, después crear el JLabel con el texto del estado como
un argumento del constructor JLabel. Poner el JLabel en la región
inferior de la ventana.

2.9. Dibujado con polimorfismo


Como se puede observar en el ejercicio 1 de la sección 2.7.1, y en la
modificación solicitada en el ejercicio 1 de la sección 2.8.1 existen muchas
similaridades entre las clases de las figuras. Usando herencia se pueden “fac-
torizar” las caracterı́sticas comunes de las tres clases y colocarlas en una sola
superclase. Se pueden entonces manipular los todos los objetos, de tres tipos
de figuras, polimórficamente usando variables del tipo de la superclase. Re-
moviendo la redundancia en el código resultará un programa más pequeño y
flexible que es más fácil de mantener.

2.9.1. Ejercicios
1. Modificar las clases MiLinea, MiElipse y MiRectangulo del ejercicio
uno de la sección 2.7.1 y 2.8.1 para crear la siguiente jerarquı́a de clases:

La clase MiFigura es una subclase de java.lang.Object


Las clases MiLinea, MiElipse y MiRectangulo son subclases de
MiFigura.

Las subclases de la jerarquı́a MiFigura deberán ser clases figura “inte-


ligentes” para saber como dibujarse ellas si se proporciona un objeto
Graphics que les diga donde dibujar. Una vez que el programa cree un
objeto de la jerarquı́a, este lo puede manipular polimórficamente por
el resto de su existencia como un MiFigura.
En la solución, la clase MiFigura deberá ser abstract. Como MiFigura
representa cualquier figura en general, no se puede implementar el
2.9. DIBUJADO CON POLIMORFISMO 33

método dibujar sin saber exactamente que figura es. Los datos re-
presentando las coordenadas y el color de las figuras en la jerarquı́a
deberán ser declarados como miembros private de la clase MiFigura.
Además de los datos comunes, la clase MiFigura deberá declarar los
siguientes métodos:

a) Un constructor sin argumentos que ponga todas las coordenadas


de la figura en cero y el color en negro.
b) Un constructor que inicialize las coordenadas y el color con los
valores de los argumentos proporcionados.
c) Métodos set para las coordenadas individuales y el color que per-
mitan al programador poner cualquier parte de los datos indepen-
dientemente para una figura en la jerarquı́a.
d ) Métodos get para las coordenadas individuales y el color que per-
mitan al programador recuperar cualquier parte de los datos in-
dependientemente para una figura en la jerarquı́a.
e) El método abstract
public abstract void dibujar( Graphics g );
el cual será llamado por el método paintComponent del programa
para dibujar una figura en la pantalla.

Para asegurar la encapsulación, todos los datos en la clase MiFigura


deberán ser private. Esto requiere declarar métodos set y get para ma-
nipular los datos. La clase MiLinea deberá proporcionar un constructor
sin argumentos y un constructor con argumentos para las coordenadas
y el color. Las clases MiElipse y MiRectangulo deberán proporcionar
un constructor sin argumentos y un constructor con argumentos para
las coordenadas, el color y para saber si la figura es rellena. El cons-
tructor sin argumentos deberá, adicionalmente de poner los valores por
defecto, fijar la figura sin relleno.
Se pueden dibujar lı́neas, rectángulos, y elipses si se conocen dos pun-
tos en el plano. Las lı́neas requieren las coordenadas x1, y1, x2 y y2.
El método drawLine de la clase Graphics conectará los dos puntos
dados con un lı́nea. Si se tienen los mismos cuatro valores para elipses
y rectángulos, se pueden calcular los argumentos necesarios para dibu-
jarlos. Cada uno requiere el valor x de la esquina superior izquierda
34 CAPÍTULO 2. CASO DE ESTUDIO

(el más pequeño de las x de las dos abscisas), y de la esquina superior


izquierda (el más pequeño de las y de las dos ordenadas), un ancho (el
valor absoluto de la diferencia de las dos abscisas) y un alto (el valor
absoluto de la diferencia de las dos ordenadas). Los rectángulos y las
elipses podrı́an también tener una bandera relleno que determine si
se dibuja la figura como rellena.
No deberá haber en el programa variables MiLinea, MiRectangulo,
o MiElipse —solamente variables MiFigura que contengan referen-
cias a objetos tipo MiLinea, MiRectangulo, o MiElipse. El programa
deberá generar figuras aleatorias y guardarlas en un arreglo del tipo
MiFigura. El método paintComponent deberá recorrer el arreglo tipo
MiFigura y dibujar cada figura (es decir, llamando polimórficamente
al método dibujar de cada figura.
Permitir al usuario indicar, con un cuadro de diálogo de entrada, el
número de figuras que se generarán. El programa entonces las genera
y las muestra con una barra de estado que informa al usuario cuantas
figuras de cada una fueron creadas.
2. En el ejercicio 1, se creo una jerarquı́a MiFigura en donde las clases
MiLinea, MiRectangulo y MiElipse extienden directamente a MiFigura.
Si la jerarquı́a fue diseñada adecuadamente, se podrá observar las simi-
laridades entre las clases MiRectangulo y MiElipse. Rediseñar y reim-
plementar el código para las clases MiRectangulo y MiElipse para fac-
torizar las caracterı́sticas comunes en la clase abstracta MiFiguraAcotada
para generar la siguiente jerarquı́a.

La clase MiFigura es una subclase de java.lang.Object


Las clases MiLinea y MiFiguraAcotada son subclases de MiFigura.
Las clases MiElipse y MiRectangulo son subclases de MiFiguraAcotada.

La clase MiFiguraAcotada deberá declarar dos constructores que imi-


ten a los de la clase MiFigura y que agreguen un parámetro para poner
si la figura es rellena. La clase MiFiguraAcotada deberá también decla-
rar métodos set y get para manipular el campo relleno y métodos que
calculen la coordenada x de la esquina superior izquierda, la coordena-
da y de la esquina superior izquierda, el ancho y el alto. Si esta bien
diseñado, las nuevas clases MiElipse y MiRectangulo deberán tener
cada una dos constructores y un método dibujar.
Bibliografı́a

[1] H. M. Deitel, Java How to Program, Sevent Edition, Prentice Hall, 2007.

[2] J. Friesen, Java SE 6 Platform: From Novice to Professional, Apress,


2007.

35

También podría gustarte