Usando la clase Graphics

Una variedad de factores inspiran a las personas a escribir programas de software. Creo que para muchos, la motivación surge del deseo de crear gráficos, manipular imágenes o animar. Ya sea que quieran crear juegos de arcade, simuladores de vuelo o paquetes CAD, los desarrolladores a menudo comienzan por aprender a dibujar.

La caja de herramientas de gráficos dentro de Abstract Windowing Toolkit (o AWT) hace posible que un programador de Java dibuje formas geométricas simples, imprima texto y coloque imágenes dentro de los bordes de un componente, como un marco, panel o lienzo.

Esta columna es la primera sobre el tema de los gráficos. Se enfocará en la Graphicsclase y sus métodos para dibujar formas geométricas simples e introducirá el proceso por el cual ocurre la pintura (y repintado).

Comencemos en el centro del escenario: la Graphicsclase.

La clase de gráficos

Es esencial que los programadores comprendan la Graphicsclase antes de intentar dibujar imágenes a través de Java. La Graphicsclase proporciona el marco para todas las operaciones gráficas dentro del AWT. Desempeña dos roles diferentes, pero relacionados. Primero, es el contexto gráfico. El contexto gráfico es información que afectará las operaciones de dibujo. Esto incluye los colores de fondo y primer plano, la fuente y la ubicación y las dimensiones del rectángulo de recorte (la región de un componente en el que se pueden dibujar los gráficos). Incluso incluye información sobre el destino final de las propias operaciones gráficas (pantalla o imagen). Segundo, elGraphicsLa clase proporciona métodos para dibujar formas geométricas simples, texto e imágenes en el destino de los gráficos. Toda la salida al destino de los gráficos se produce mediante la invocación de uno de estos métodos.

Para dibujar, un programa requiere un contexto gráfico válido (representado por una instancia de la Graphicsclase). Debido a que la Graphicsclase es una clase base abstracta, no se puede instanciar directamente. Normalmente, un componente crea una instancia y la entrega al programa como argumento para los métodos update () y paint () de un componente . Estos dos métodos, junto con el método repaint () , se analizan en la siguiente sección.

Los métodos

Los siguientes tres métodos están involucrados en la visualización de gráficos. Las versiones predeterminadas de cada uno se proporcionan por clase Component. Los métodos update () y paint () deben redefinirse para realizar las operaciones gráficas deseadas.

repintar ()

repintado de vacío público () repintado de vacío público (tm largo) repintado de vacío público (int x, int y, int w, int h) repintado de vacío público (tm largo, int x, int y, int w, int h)

El método repaint () solicita que se vuelva a pintar un componente. La persona que llama puede solicitar que se vuelva a pintar lo antes posible, o puede especificar un período de tiempo en milisegundos. Si se especifica un período de tiempo, la operación de pintura ocurrirá antes de que transcurra el período de tiempo. La persona que llama también puede especificar que solo se vuelva a pintar una parte de un componente. Esta técnica es útil si la operación de pintura requiere mucho tiempo y solo es necesario volver a pintar una parte de la pantalla. El código del Listado 1 ilustra cómo se puede usar el método repaint () en un programa.

boolean mouseDown (Evento e, int x, int y) {objeto_seleccionado.move (x, y); repintar (); }

Listado 1: controlador de eventos con el mouse hacia abajo

El código en el controlador de eventos mouseDown () recalcula la posición de un objeto en una pantalla basándose en la posición del mouse y llama al método repaint () para indicar que la pantalla debe volver a pintarse lo antes posible.

actualizar()

actualización de vacío público (Gráficos g)

El método update () se llama en respuesta a una solicitud de repaint () , o en respuesta a una parte del componente que se descubre o muestra por primera vez. El único argumento del método es una instancia de la Graphicsclase. La Graphicsinstancia es válida solo dentro del contexto del método update () (y cualquier método que llame), pero se elimina poco después de que regrese el método update () . La implementación predeterminada proporcionada por la Componentclase borra el fondo y llama al método paint () (abajo).

pintar()

pintura de vacío público (Gráficos g)
El método paint () se llama desde un método update () y es responsable de dibujar los gráficos. El único argumento del método es una instancia de la Graphicsclase. La implementación predeterminada proporcionada por la clase Componentno hace nada.

Cómo se repintan los componentes

Para reducir el tiempo necesario para volver a pintar la pantalla, el AWT utiliza dos atajos:

  • Primero, el AWT repinta solo aquellos componentes que necesitan ser repintados, ya sea porque han sido descubiertos o porque pidieron ser repintados.


    
  • En segundo lugar, si se cubrió un componente y se descubrió, el AWT vuelve a pintar solo la parte del componente que se cubrió anteriormente.

El subprograma de la Figura 1 le permite observar este proceso a medida que ocurre. Ignore el área de texto en la parte superior del subprograma por un momento y observe solo la parte coloreada de la pantalla. Usando otra ventana, cubra momentáneamente y luego descubra parte del subprograma. Observe que solo se vuelve a pintar la parte del subprograma que se cubrió. Además, solo se repintan los componentes que se cubrieron, sin importar su posición en la jerarquía de componentes. Al usar deliberadamente diferentes colores, el subprograma hace que este efecto sutil sea notable. El código fuente de esta figura está disponible aquí.

Figura 1: Repintar el navegador

El sistema de coordenadas de gráficos

Los métodos descritos en la siguiente sección toman, como parámetros, valores que especifican cómo se dibujará una forma. Por ejemplo, el método drawLine () espera cuatro parámetros. Los dos primeros parámetros especifican la ubicación del comienzo de la línea y los dos últimos parámetros especifican la ubicación del final de la línea. Los valores exactos que se pasarán al método drawLine () están determinados por el sistema de coordenadas en vigor.

Un sistema de coordenadas es un método para especificar sin ambigüedades la ubicación de puntos en el espacio. En el caso del AWT, este espacio es una superficie bidimensional llamada plano. Cada ubicación en un plano se puede especificar mediante dos números enteros, llamado el X y Y coordenadas. Los valores de las x y Y coordenadas se calculan en términos de respectivo desplazamiento horizontal y vertical de la punto del origen. En el caso del AWT, el origen siempre es el punto en la esquina superior izquierda del plano. Tiene los valores de coordenadas 0 (para x ) y 0 (para y). La ilustración de la Figura 2 muestra dos puntos: uno ubicado en el origen y otro ubicado en una posición siete a lo ancho y cinco hacia abajo desde el origen.

Figura 2: El plano de coordenadas

Las primitivas gráficas

Esta sección presenta métodos para dibujar líneas, rectángulos, óvalos y arcos y polígonos. Dado que estos métodos funcionan solo cuando se invocan en una Graphicsinstancia válida , solo se pueden usar dentro del alcance de los métodos update () y paint () de un componente . La mayoría de los métodos que siguen vienen en pares. Un método (el método drawX () ) dibuja solo el contorno de la forma especificada, y el otro método (el método fillX () ) dibuja una versión completa de la forma especificada.

líneas

vacío drawLine (int xBegin, int yBegin, int xEnd, int yEnd)

Este es el más simple de todos los métodos gráficos. Dibuja una línea recta, de un solo píxel de ancho, entre los puntos inicial y final especificados. La línea resultante se recortará para ajustarse a los límites de la región de recorte actual. La línea se dibujará con el color de primer plano actual.

El subprograma de la Figura 3 muestra el método drawLine () en acción. El código fuente está disponible aquí. Este subprograma y los subprogramas de las Figuras 4, 6 y 7 requieren los servicios de dos clases de soporte: la clase NewCanvas y la interfaz Figura. La clase NewCanvas amplía la clase Canvas y proporciona una superficie de dibujo especializada para figuras. El código fuente de la clase NewCanvas está disponible aquí. La interfaz de Figura define los métodos que una figura debe proporcionar para ser utilizada con NewCanvas. El código fuente de la interfaz de Figura está disponible aquí.

Figura 3: demostración de dibujo lineal

rectángulos
vacío drawRect (int x, int y, int w, int h) vacío fillRect (int x, int y, int w, int h) vacío drawRoundRect (int x, int y, int w, int h, int arcWidth, int arcHeight ) void fillRoundRect (int x, int y, int w, int h, int arcWidth, int arcHeight) void draw3DRect (int x, int y, int w, int h, boolean elevado) void fill3DRect (int x, int y, int w, int h, booleano elevado)

Cada uno de estos métodos gráficos requiere, como parámetros, las coordenadas xey en las que comenzar el rectángulo, y el ancho y alto del rectángulo. Tanto el ancho como el alto deben ser números enteros positivos. El rectángulo resultante se recortará para ajustarse a los límites de la región de recorte actual. El rectángulo se dibujará con el color de primer plano actual. Los rectángulos vienen en tres estilos diferentes: lisos, con esquinas redondeadas y con un ligero (pero a menudo difícil de ver) efecto tridimensional.

Los métodos de gráficos de rectángulo redondeado requieren dos parámetros adicionales, un ancho de arco y una altura de arco, los cuales controlan el redondeo de las esquinas. Los métodos del rectángulo tridimensional requieren un parámetro adicional que indique si el rectángulo debe estar hundido o elevado.

El subprograma de la Figura 4 muestra estos métodos en acción. El código fuente está disponible aquí.

Figura 4: Demostración de dibujo de rectángulo

óvalos y arcos

vacío drawOval (int x, int y, int w, int h) void fillOval (int x, int y, int w, int h) void drawArc (int x, int y, int w, int h, int startAngle, int arcAngle ) vacío fillArc (int x, int y, int w, int h, int startAngle, int arcAngle)

Cada uno de estos métodos gráficos requiere, como parámetros, las coordenadas xey del centro del óvalo o arco, y el ancho y alto del óvalo o arco. Tanto el ancho como el alto deben ser números enteros positivos. La forma resultante se recortará para ajustarse a los límites de la región de recorte actual. La forma se dibujará con el color de primer plano actual.

The arc graphics methods require two additional parameters, a start angle and an arc angle, to specify the beginning of the arc and the size of the arc in degrees (not radians). Figure 5 illustrates how angles are specified.

Figure 5: Angle specification

The applet in Figure 6 demonstrates these methods in action. The source code is available here.

Figure 6: Oval and arc drawing demonstration

polygons

void drawPolygon(int xPoints[], int yPoints[], int nPoints) void drawPolygon(Polygon p) void fillPolygon(int xPoints[], int yPoints[], int nPoints) void fillPolygon(Polygon p)

Polygons are shapes formed from a sequence of line segments. Each of the polygon graphics methods require, as parameters, the coordinates of the endpoints of the line segments that make up the polygon. These endpoints can be specified in either one of two ways: as two parallel arrays of integers, one representing the successive x coordinates and the other representing the successive y coordinates; or with an instance of the Polygon class. The Polygon class provides the method addPoint(), which allows a polygon definition to be assembled point by point. The resulting shape will be clipped to fit within the boundaries of the current clipping region.

The applet in Figure 7 demonstrates these methods in action. The source code is available here.

Figura 7: demostración de dibujo de polígono

Conclusión

Lo crea o no, estas pocas primitivas gráficas simples, combinadas con todo lo que hemos cubierto en los últimos meses (el AWT, manejo de eventos, observadores, etc.) son todo lo que necesita para escribir un montón de aplicaciones útiles, que van desde juegos a sistemas CAD. El mes que viene, juntaré todas estas piezas y les mostraré lo que quiero decir.

Manténganse al tanto.

Todd Sundsted ha estado escribiendo programas desde que las computadoras estuvieron disponibles en modelos de escritorio. Aunque originalmente estaba interesado en construir aplicaciones de objetos distribuidos en C ++, Todd se mudó al lenguaje de programación Java cuando Java se convirtió en la opción obvia para ese tipo de cosas. Además de escribir, Todd ofrece servicios de consultoría de Internet y Web a empresas del sureste de los Estados Unidos. : END_BIO

Más información sobre este tema

  • La GraphicsAPI de clase Java

    //java.sun.com/products/JDK/CurrentRelease/api/java.awt.Graphics.html

  • Observador y observable //www.sun.com/javaworld/jw-10-1996/jw-10-howto.html
  • La interfaz de usuario eficaz //www.sun.com/javaworld/jw-09-1996/jw-09-userint.html
  • Java y manejo de eventos //www.sun.com/javaworld/jw-08-1996/jw-08-event.html
  • Introducción al AWT //www.sun.com/javaworld/jw-07-1996/jw-07-awt.html

Esta historia, "Uso de la clase Graphics", fue publicada originalmente por JavaWorld.