>>
Lección 09

Gráficos, colores y letras.


Gráficos.


Los gráficos en Java se tratan con unas pocas clases del paquete java.awt. La más importante de estas clases es java.awt.Graphics.

Las variables privadas de java.awt.Graphics guardan el color para dibujar, el modo de dibujo (XOR o normal), y la información necesaria sobre el espacio en el que se va a dibujar. Se puede dibujar sobre cualquier componente, es decir, sobre cualquier objeto de tipo java.awt.Component. El método getGraphics() de java.awt.Component devuelve un objeto de tipo Graphic listo para realizar dibujos. Casi siempre se dibuja sobre alguna de las subclases Canvas, Panel o Applet de Component. En esta lección nos limitaremos a utilizar los componentes sin entrar en los detalles de su contrucción y su despliegue.

El siguiente Applet ilustra cómo se utiliza la clase Graphics para dibujar.

Aquí vería un applet si su navegador reconociese la etiqueta de APPLET.
Aquí vería un applet si su navegador reconociese la etiqueta de APPLET.

Como puede apreciarse en el código del Applet, los dibujos se realizan dentro del método public void paint(Graphics g). Este método es invocado por el navegador o el intérprete de Java cada vez que es necesario pintar la superficie asignada al applet. El propio sistema se encarga de pasarle al método un objeto de la clase Graphics que puede utilizarse directamente para realizar los dibujos.

En el ejemplo se utilizan algunos de los métodos de la clase Graphics como drawLine, drawRect y drawOval y también se ilustra cómo se escogen los colores llamando al método setColor al que se le pasan los colores mediante unos objetos constantes de la clase java.awt.Color, que se estudia en la siguiente sección.

Ésta es una lista de los métodos y variables de la clase Graphics que se utilizan para dibujar, con una breve descripción. Todos los métodos devuelven void y son públicos. Los rectángulos se especifican con cuatro variables de tipo int: x,y,width y height que son las coordenadas del punto arriba a la izquierda del rectángulo, su ancho y su alto. Por brevedad en la escritura, utilizaremos los símbolos w y h en lugar de width y depth.

clearRect(int x,int y,int w,int h) Llena el rectángulo con el color de fondo.
(Este método no se recomienda, es mejor utilizar fillRect.)
clipRect(int x,int y,int w,int h) Limita la acción de dibujo al rectángulo.
copyArea(int x,int y,int w,int h,int dx,int dy) Copia el rectángulo al punto (x+dx,y+dy).
draw3DRect(int x,int y,int w,int h,boolean elevado)

Dibuja un rectángulo remarcado.

drawArc(int x,int y,int w,int h,int ai,int af) Dibuja un arco elíptico inscrito en el rectángulo, con ángulo inicial ai y ángulo final af.
drawBytes(byte[] data,int L,int x,int y) Escribe el texto de los primeros L bytes de data, a partir de x,y.
drawChars(char[] data,int L,int x,int y) Escribe el texto de los primeros L chars de data, a partir de x,y.
drawImage(Image img,int x,int y,ImageObserver io) Dibuja la imagen img a partir de x,y. io el objeto que deberá ser notificado cuando la imagen termina de cargarse. Normalmente se utiliza this como ImageObserver
drawImage(Image img,int x,int y,Color bgc, ImageObserver io) Igual que el anterior pero los pixels transparentes se dibujan de color bgc.
drawImage(Image img,int x,int y,int w,int h, ImageObserver io) Dibuja la imagen img a partir de x,y y acomodándola a un ancho w y un alto h. Este método puede ampliar o reducir la imagen.
drawImage(Image img,int x,int y,int w,int h, Color bgc,ImageObserver io) Combina la función de los dos métodos anteriores.
drawLine(int x1,int y1,int x2,int y2) Dibuja una línea recta del punto x1,y1 al punto x2,y2. Este método no utiliza un rectángulo como referencia para el dibujo.
drawOval(int x,int y,int w,int h) Dibuja una elipse contenida en el rectángulo.
drawPolygon(int[] x,int[] y,int N) Dibuja el polígono de N vértices con las coordenadas especificadas.
drawPolygon(Polygon p) Dibuja el polígono p (una clase especial del awt).
drawRect(int x,int y,int w,int h) Dibuja el rectángulo.
drawRoundRect(int x,int y,int w,int h,int aw,int ah) Dibuja un rectángulo con vértices redondeados. aw es el ancho del arco y ah el alto.
drawString(String s,int x,int y) Escribe el texto de la cadena s, a partir de x,y.
fill3DRect(int x,int y,int w,int h,boolean elevado) Rellena rectángulo remarcado.
fillArc(int x,int y,int w,int h,int ai,int af) Rellena un arco elíptico inscrito en el rectángulo, con ángulo inicial ai y ángulo final af.
fillOval(int x,int y,int w,int h) Rellena una elipse contenida en el rectángulo.
fillPolygon(int[] x,int[] y,int N) Rellena el polígono de N vértices con las coordenadas especificadas.
fillPolygon(Polygon p) Rellena el polígono p (una clase especial del awt).
fillRect(int x,int y,int w,int h) Rellena el rectángulo.
fillRoundRect(int x,int y,int w,int h,int aw,int ah) Rellena un rectángulo con vértices redondeados. aw es el ancho del arco y ah el alto.
setColor(Color c) Fija el color para dibujar.
setFont(Font f) Fija la fuente de letras para escribir.
setPaintMode() Fija el estilo normal para dibujar (quita el XOR).
setXORMode(Color c1) Fija el estilo XOR para dibujar. En particular dibuja en color c1 los pixels de color c (el de setColor) y viceversa.

Graphics tiene otros métodos para obtener el color de dibujo y la fuente de letras, que el alumno puede consultar en las referencias, pero éstos son todos los métodos que se utilizan para dibujar.

El siguiente applet muestra dibujos en donde se utilizan casi todos estos métodos. El alumno debe buscar y estudiar el código correspondiente a cada dibujo. Observará que la imagen se prepara antes cargándola con el método getImage.

La siguiente sección explica la estructura y uso de los colores en Java.


Colores.


La clase java.awt.Color se utiliza para representar cualquier color. En primer lugar, hay varios colores predefinidos en la clase Color que son los que aparecen en la siguiente tabla con sus nombres en castellano y sus componentes de rojo, verde y azul en la escala de 0 a 255.

black negro rojo=0, verde=0, azul=0
darkGray gris oscuro rojo=64, verde=64, azul=64
gray gris rojo=128, verde=128, azul=128
lightGray gris claro rojo=192, verde=192, azul=192
white blanco rojo=255, verde=255, azul=255
magenta magenta rojo=255, verde=0, azul=255
blue azul rojo=0, verde=0, azul=255
cyan cian rojo=0, verde=255, azul=255
green verde rojo=0, verde=255, azul=0
yellow amarillo rojo=255, verde=255, azul=0
orange naranja rojo=255, verde=200, azul=0
red rojo rojo=255, verde=0, azul=0
pink rosa rojo=255, verde=175, azul=175

Los demás colores se crean usando alguno de los constructores de la clase Color:

c=new Color(int rojo,int verde,int azul)

crea un color c con las cantidades indicadas de rojo, verde y azul cuyos valores deben estar entre 0 y 255. Igualmente

c=new Color(double r,double v,double a)

crea un color con r,v y a partes de rojo, verde y azul respectivamente, sólo que en este caso r, v y a deben ser números entre 0.0 y 1.0. Finalmente:

c=new Color(int i)

también crea un color y también lo hace especificando sus partes de rojo, verde y azul, sólo que lo hace implícitamente. Supongamos que la representación hexadecimal de i es por ejemplo 0xffc08040. Entonces el color creado tiene 0xc0=192 de rojo, 0x80=128 de verde y 0x40=64 de azul. Los ocho bits más altos no contribuyen al color, sin embargo, una imagen suele representarse con un int para cada pixel y el color del pixel coincide con el que se crearía de esta manera, pero además si los bits más altos no están encendidos, es decir si no comienza con 0xff, entonces el pixel resulta parcial o totalmente transparente.

El siguiente applet muestra al centro el color que se obtiene con cada combinación de rojo, verde y azul en la escala de 0 a 255. Las barras de desplazamiento permiten elegir cualquier combinación deseada.


Aquí vería un applet si su navegador reconociese la etiqueta de APPLET.
Aquí vería un applet si su navegador reconociese la etiqueta de APPLET.

El alumno puede usar las barras de desplazamiento para igualar los colores predefinidos (compare su resultado con los valores de la tabla). Conviene que el alumno observe el código del applet y se vaya familiarizando con la construcción, configuración y despliegue de los componentes y con el tratamiento de eventos, que se estudiarán en las próximas lecciones. Presentamos otra versión más sencilla de este applet pero que recibe su color inicial como parámetros en expresión hexadecimal y también tiene un método público String getColor() que devuelve el color en expresión hexadecimal.

 

Aquí vería un applet si su navegador reconociese la etiqueta de APPLET. Aquí vería un applet si su navegador reconociese la etiqueta de APPLET.

Este applet se usará en la sección de JavaScript, para definir colores en otro applet.

La siguiente sección explica cómo se utilizan las fuentes de letras.


Letras.


Las fuentes de letras se representan con objetos de la clase java.awt.Font que tiene un solo constructor:

Font f=new Font(String nombre,int estilo,int tamaño)

En este constructor todos los parámetros tienen un conjunto limitado de posiblidades. El nombre tiene que ser uno de los que aparecen en la siguiente tabla, donde también aparecen los nombres de las fuentes equivalentes de Windows.

"Helvetica" "Arial"
"TimesRoman" "Times New Roman"
"Courier" "Courier New"
"Dialog" "MS Sans Serif"
"DialogInput" "MS Sans Serif"
"ZapfDingbats" "WingDings"

Es necesario usar los nombre a la izquierda de la tabla, que son los propios de Java.

Hay sólo cuatro estilos que se obtienen usando tres constantes de la clase Font, como se muestra en la tabla.

Font.PLAIN estilo
Font.BOLD estilo
Font.ITALIC estilo
Font.BOLD+Font.ITALIC estilo

Finalmente, el tamaño debe ser un entero mayor que 6. El tamaño se mide en "puntos". Estos "puntos" representan el tamaño vertical de las letras a razón de poco más de un pixel por "punto", aproximadamente. Esto no es exacto porque las fuentes están diseñadas para las impresoras y no para la pantalla. Hay 72 "puntos" en una pulgada o aproximadamente 28 puntos en un centímetro, así que una fuente de 14 puntos medirá medio centímetro de alto cuando se imprime en papel. La representación en la pantalla corresponde a poco más de un pixel por punto, o más precisamente, una fuente de 12 puntos ocupa unos 12 pixels en sentido vertical. El valor exacto se obtiene usando la clase FontMetrics, como se explica más adelante.

En este applet se pueden ver los diferentes tipos de letras, estilos y tamaños. El alumno debe observar el aspecto del texto eligiendo diversas fuentes, estilos y tamaños.


Aquí vería un applet si su navegador reconociese la etiqueta de APPLET.

Aquí está el código del applet:

Aquí vería un applet si su navegador reconociese la etiqueta de APPLET.

Conviene que el alumno memorice los nombres de las fuentes y aprenda a construir la fuente que desee eligiendo los parámetros adecuados para el constructor. Para ello conviene que estudie detenidamente el código del applet. Conviene también que observe la construcción de los componentes y el tratamiento de los eventos, que se estudiarán detenidamente en la lección 5.

Nota: En Java 2 se pueden usar las otras fuentes del sistema, pero sólo en las aplicaciones autónomas, en los applets no se puede pues éstos no tienen acceso al sistema.

Si se desea dibujar texto con precisión es importante conocer la clase java.awt.FontMetrics que es la que nos informa de todas las medidas de una fuente de letras.

El último ejemplo de esta lección ilustra el significado de las diversas variables de la clase FontMetrics. El alumno debe observar los valores de las variables y el aspecto de la palabra escrita eligiendo diversas fuentes, estilos y tamaños.


Aquí vería un applet si su navegador reconociese la etiqueta de APPLET.

Aquí está el código del applet:

Aquí vería un applet si su navegador reconociese la etiqueta de APPLET.

Observe que el objeto FontMetrics que se usa en el ejemplo se obtiene del objeto Graphics al cual se le ha asignado la fuente de letras con la que se va a escribir.

El método drawString(String s,int x,int y) comienza a dibujar la cadena usando y como altura para la línea base. El ascenso es el número de pixels que una letra (del alfabeto alfanumérico básico) puede llegar a subir sobre la línea base y el descenso (Descent) es lo que puede llegar a bajar. "Leading" es el número de pixels que se recomienda agregar, además del descenso y el ascenso, para llegar a la línea base del siguiente renglón. Gráficamente aparece representado por la distancia entre la línea superior y la segunda que corresponde al ascenso. La fuente "Courier" tiene Leading nulo. El alumno podrá observar que la altura (Height) es (casi siempre) igual al ascenso más el descenso más el "Leading". También observará que la altura (Height) es siempre un poco mayor que el "tamaño" de la fuente.

El método getMaxAdvance() devuelve el máximo avance (en la dirección horizontal) con una sola letra.

El método stringWidth(String s) devuelve la longitud, en pixels, de la cadena s en la fuente que dio lugar al objeto FontMetrics.

Los métodos getMaxDescent y getMaxAscent devuelven el ascenso y descenso máximos, que quiere decir, incluyendo el alfabeto completo con letras acentuadas y otros caracteres. Casi siempre el ascenso máximo coincide con el ascenso y el descenso máximo coincide con el descenso.


Índice

Ejercicios de la Lección 09.


José Luis Abreu y Marta Oliveró