## Dibujar Formas Sencillas

La clase Graphics define métodos para dibujar los siguientes tipos de formas:

- Líneas (drawLine(), que dibuja una línea en el color actual del objeto Graphics, que es inicializado con el color de primer plano del Componente)
- Rectángulos (drawRect(), fillRect(), y clearRect() -- donde fillRect() rellena un rectángulo con el color actual del objeto Graphics, y clearRect() rellena un rectángulo con el color de fondo del Componente)
- Rectángulos en 3 dimensiones (draw3DRect() y fill3DRect())
- Rectángulos con los bordes redondeados (drawRoundRect() y fillRoundRect())
- Ovalos (drawOval() y fillOval())
- Arcos (drawArc() y fillArc())
- Polígonos (drawPolygon() y fillPolygon())

Excepto para los polígonos y las líneas todas las formas son especificas utilizando su rectángulo exterior. Una vez que hayas comprendido el dibujo de rectángulos, las otras formas son relativamente sencillas. Por esta razón, esta página se concentra en el dibujo de rectángulos.

### Ejemplo 1: Dibujar un Rectángulo Sencillo

> El applet de la página anterior utilizaba los métodos draw3DRect() y fillRect() para dibujar su interface. Aquí tienes el applet de nuevo:

> Aquí puedes ver el código. Abajo sólo tienes el código de dibujo:

>     //en  FramedArea (una subclase de Panel):
>     public void paint(Graphics g) {
>         Dimension d = size();
>         Color bg = getBackground();

>         //Dibuja un marco divertido alrededor del applet.
>         g.setColor(bg);
>         g.draw3DRect(0, 0, d.width - 1, d.height - 1, true);
>         g.draw3DRect(3, 3, d.width - 7, d.height - 7, false);
>     }

>     //en CoordinateArea (una subclase de Canvas):
>     public void paint(Graphics g) {
>         //Si el usuario pulsa el ratón, dibuja un rectángulo pequeñito en esa posición
>         if (point != null) {
>             g.fillRect(point.x - 1, point.y - 1, 2, 2);
>         }
>     }

El applet crea (y contiene) un objeto FramedArea, que crea (y contiene) un objeto CoordinateArea. La primera llamada a draw3DRect() crea un rectángulo tan grande como el área de dibujo del FramedArea. El argumento true especifica que el rectángulo debe aparecer elevado. La segunda llamada a draw3DRect() crea un segundo rectángulo un poquito menor, con false especifica que el rectángulo deberá aparcer embebido. Las dos llamadas juntas producen el efecto de un marco elvado que contiene el CoordinateArea. (FramedArea implementa el método insets() para que el área de dibujo de la CoordinateArea esté unos pixels dentro del FramedArea.)

El CoordinateArea utiliza fillRect() para dibujar un rectángulo de 2x2 pixles en el punto en el que el usuario pulsa el botón del ratón.

### Ejemplo 2: Utilizar un Rectángulo para Indicar un Area Seleccionada

> Aquí tienes un applet que podrías utilizar para implementar la selección básica en un programa de dibujo. Cuando el usuario mantiene pulsado el botón del ratón, el applet muestra continuamente un rectángulo. El rectángulo empieza en la posición del cursor cuando el usuario pulsó el botón del ratón por primera vez y termina en la posición actual del cursor.

> Aquí tienes el código del applet. Abajo tienes el código más importante:

>     class SelectionArea extends Canvas {
>         . . .

>         public boolean mouseDown(Event event, int x, int y) {
>             currentRect = new Rectangle(x, y, 0, 0);
>             repaint();
>             return false;
>         }

>         public boolean mouseDrag(Event event, int x, int y) {
>             currentRect.resize(x - currentRect.x, y - currentRect.y);
>             repaint();
>             return false;
>         }

>         public boolean mouseUp(Event event, int x, int y) {
>             currentRect.resize(x - currentRect.x, y - currentRect.y);
>             repaint();
>             return false;
>         }

>         public void paint(Graphics g) {
>             Dimension d = size();

>             //Si existe currentRect exists, dibuja un rectángulo.
>             if (currentRect != null) {
>                 Rectangle box = getDrawableRect(currentRect, d);
>                 controller.rectChanged(box);

>                 //Draw the box outline.
>                 g.drawRect(box.x, box.y, box.width - 1, box.height - 1);
>             }
>         }

>         Rectangle getDrawableRect(Rectangle originalRect, Dimension drawingArea) {
>             . . .
>             //Asegurese de que las dimensiones de altura y anchura del rectángulo son positiva.
>             . . .
>             //El rectángulo no debe sobrepasar el área de dibujo.
>             . . .
>         }
>     }

> Como puedes ver, el SelectionArea sigue la pista del rectángulo seleccionado actualmente, utilizando un objeto Rectangle llamado currentRect. Debido a la implementación, el currentRect mantiene el mismo origen (currentRect.x, currentRect.y) mientras el usuario arrrastre el ratón. Esto significa que la altura y anchura del rectángulo podrían ser negativas.

> Sin embargo, los métodos drawXxx() y fillXxx() no dibujarán nada si su altura o anchura son negativos. Por esta razón, cuando SelectionArea dibuja un rectángulo, debe especificar el vértice superior izquierdo del rectángulo para que la altura y la anchura sean positivas. La clase SelectionArea define el método getDrawableRect() para realizar los cálculos necesarios para encontrar el vértice superior izquierdo. El getDrawableRect() método también se asegura de que el rectángulo no sobrepase los límites de su área de dibujo. Aquí tienes de nuevo un enlace al código fuente. Encontrarád la definición de getDrawableRect() al final del fichero.

> Nota: Es perfectamente legal especificar valores negativos para x, y, height o width o hacer que el resultado sea mayor que el área de dibujo. Los valores fuera del área de dibujo no importan demasiado porque son recortardos al área de dibujo. Lo único es que no verás una parte de la forma. La altura o anchura negativas dan como resultado que no se dibujará nada en absoluto.

### Ejemplo 3: Un Ejemplarizador de Formas

> El siguiente applet demuestra todas las formas que se pueden dibujar y rellenar.

> A menos que la fuente por defecto de su visualizador de applets sea muy pequeña, el texto mostrado en el applet anterior podría parecer demasiado grande en ocasiones. La palabras podrían dibujarse unas sobre otras. Y como este applet no utiliza el método insets() para proteger sus límites el texto podría dibujarse sobre el marco alrededor del applet. La siguiente página amplía este ejemplo, enseñándolo como hacer que el texto quepa en un espacio dado.

> Aquí tienes el código para el applet anterior. Abajo sólo tienes el código que dibuja las formas geométricas. Las variables rectHeight y rectWidth especifican el tamaño en pixels del área en que debe dibujarse cada forma. Las variables x y y se cambian para cada forma, para que no se dibujen unas sobre otras.

>     Color bg = getBackground();
>     Color fg = getForeground();
>     . . .

>     // drawLine()
>     g.drawLine(x, y+rectHeight-1, x + rectWidth, y); // x1, y1, x2, y2
>     . . .

>     // drawRect()
>     g.drawRect(x, y, rectWidth, rectHeight); // x, y, width, height
>     . . .

>     // draw3DRect()
>     g.setColor(bg);
>     g.draw3DRect(x, y, rectWidth, rectHeight, true);
>     g.setColor(fg);
>     . . .

>     // drawRoundRect()
>     g.drawRoundRect(x, y, rectWidth, rectHeight, 10, 10); // x, y, w, h, arcw, arch
>     . . .

>     // drawOval()
>     g.drawOval(x, y, rectWidth, rectHeight); // x, y, w, h
>     . . .

>     // drawArc()
>     g.drawArc(x, y, rectWidth, rectHeight, 90, 135); // x, y, w, h
>     . . .

>     // drawPolygon()
>     Polygon polygon = new Polygon();
>     polygon.addPoint(x, y);
>     polygon.addPoint(x+rectWidth, y+rectHeight);
>     polygon.addPoint(x, y+rectHeight);
>     polygon.addPoint(x+rectWidth, y);
>     //polygon.addPoint(x, y); //don't complete; fill will, draw won't
>     g.drawPolygon(polygon);
>     . . .

>     // fillRect()
>     g.fillRect(x, y, rectWidth, rectHeight); // x, y, width, height
>     . . .

>     // fill3DRect()
>     g.setColor(bg);
>     g.fill3DRect(x, y, rectWidth, rectHeight, true);
>     g.setColor(fg);
>     . . .

>     // fillRoundRect()
>     g.fillRoundRect(x, y, rectWidth, rectHeight, 10, 10); // x, y, w, h, arcw, arch
>     . . .

>     // fillOval()
>     g.fillOval(x, y, rectWidth, rectHeight); // x, y, w, h
>     . . .

>     // fillArc()
>     g.fillArc(x, y, rectWidth, rectHeight, 90, 135); // x, y, w, h
>     . . .

>     // fillPolygon()
>     Polygon filledPolygon = new Polygon();
>     filledPolygon.addPoint(x, y);
>     filledPolygon.addPoint(x+rectWidth, y+rectHeight);
>     filledPolygon.addPoint(x, y+rectHeight);
>     filledPolygon.addPoint(x+rectWidth, y);
>     //filledPolygon.addPoint(x, y);
>     g.fillPolygon(filledPolygon);

Ozito