Está en la página 1de 120

TutorJava recomienda...

Grficos con Java 2D Autor-Traductor: Juan Antonio Palos (Ozito) Puedes encontrar la Version Original en Ingles en ( http://java.sun.com)
Leer comentarios (0)
|

Escribir comentario

Puntuacin:

(1 voto)

Vota

Indice de contenidos q Grficos en 2 Dimensiones


q q

Introduccin al API 2D de Java Renderizado en Java 2D Contexto de Renderizado de Graphics2D r Mtodos de renderizado de Graphics2D Sistema de Coordenadas
r

q q

Formas 2D Formas Rectangulares r QuadCurve2D y CubicCurve2D r GeneralPath r Areas Texto en Java 2D


r

q q q q

Fuentes r Distribucin de Texto Imgenes


r

Impresin Mostrar Grficos con Graphics2D Punteado y Relleno de Grficos Primitivos Dibujar Curvas r Ejemplo: Quad r Ejemplo: Cubic r Dibujar formas arbitrarias r Ejemplo: Odd_Shape r Definir Estilos de lnea divertidos y Patrones de relleno. r Estilos de Lnea r Patrn de Relleno r Ejemplo: StrokeAndFill Transformar Formas, Texto e Imgenes
r

Ejemplo: Transform Recortar la Regin de Dibujo


r

Ejemplo: ClipImage r Ejemplo: Starry Componer Grficos


r

q q

Ejemplo: Composite Controlar la Calidad del Dibujo


r

Construir Formas Complejas desde Geomtricos Primitivos


r

Ejemplo: Areas

Soportar Interaccin con el Usuario Ejemplo: ShapeMover r Ejemplo: HitTestSample Trabajar con Texto y Fuentes
r

Crear y Derivar Fuentes r Dibujar Mltiples Lneas de Texto Crear y Derivar Fuentes
r

Ejemplo: FontSelection Dibujar Mltiples Lneas de Texto


r

Ejemplo: LineBreakSample Mostrar y Manipular Imgenes


r

q q

Modo Inmediato con BufferedImage r Filtrado y BufferedImage r Usar un BufferedImage para doble buffer Modo Inmediato con BufferedImage
r

Filtrar un BufferedImage Ejemplo: ImageOps Usar un BufferedImage para Doble Buffer


r

Ejemplo: BufferedShapeMover Imprimir en Java


r

Introduccin a la Impresin en Java r Imprimir los Contenidos de un Componente r Mostrar el dilogo 'Page Setup' r Imprimir una Coleccin de Pginas Introduccin a la Impresin en Java
r

Job Control r Imaging r Printable Jobs r Pageable Jobs Imprimir los Contenidos de un Componente
r

q q

Ejemplo: ShapesPrint Mostrar el Dilogo de Configuracin de Pgina


r

Imprimir una Coleccin de Pginas Ejemplo: SimpleBook Problemas Ms Comunes en los Grficos en Java 2D
r
|

Leer comentarios (0)

Escribir comentario

Puntuacin:

(1 voto)

Vota

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Grficos en 2 Dimensiones

Grficos en 2 Dimensiones
Esta seccin nos presenta el API 2D de Java y no ensea como mostrar e imprimir grficos en 2 dimensiones en nuestros programas Java. El API 2D de Java nos permite fcilmente:
q q q q

Dibujar lneas de cualquier anchura Rellenar formas con gradientes y texturas Mover, rotar, escalar y recortar texto y grficos. Componer texto y grficos solapados.

Por ejemplo, podramos usar el API 2D de Java para mostrar grficos y charts complejos que usan varios estilos de lnea y de relleno para distinguir conjuntos de datos, como se muestra en la siguiente figura:

El API 2D de Java tambin nos permite almacenar datos de imgenes--por ejemplo, podemos realizar fcilmente filtros de imgenes, como blur o recortado, como se muestra en la siguiente figura:

Esta ruta cubre los usos ms frecuentes del API 2D de Java y describe brevemente algunas de las caractersticas ms avanzadas. Para ms informacin sobre el uso del API 2D de Java, puedes ver Java 2D Programmer's Guide. Introduccin al API 2D de Java presenta los conceptos claves del 2D y describe su modelo de dibujado. Mostrar Grficos con Graphics2D nos ensea como configurar el contexto de dibujado Graphics2D para usar estilos de punteado y relleno divertidos, realizar transformaciones, recortar la regin de dibujo, componer grficos solapados, y especificar preferencias de dibujado. Trabajar con Texto y Fuentes muestra como usar un objeto Font para crear una fuente con los atributos deseados, y para deribar una nueva fuente cambiando los atributos, determinar los nombres de las fuentes que estn disponibles en nuestro sistema y la posicin del texto dentro de un componente. Manipular y Mostrar Imgenes esta leccin explica como implementar doble buffer y cmo realizar operaciones de filtrado de imgenes con objetos BufferedImage. Imprimir nos ensea como renderizar grficos 2D en una impresora y cmo imprimir documentos complejos. Resolver Problemas ms Comunes con los Grficos 2D ofrece las soluciones a algunos de los problemas que nos podramos encontrar al escribir applets y aplicaciones 2D.

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Introduccin al API 2D de Java

Introduccin al API 2D de Java


El API 2D de Java introducido en el JDK 1.2 proporciona grficos avanzados en dos dimensiones, texto, y capacidades de manejo de imgenes para los programas Java a travs de la extensin del AWT. Este paquete de rendering soporta lneas artsticas, texto e imgenes en un marco de trabajo flexible y lleno de potencia para desarrollar interfaces de usuario, programas de dibujo sofisticados y editores de imgenes. El API 2D de Java proporciona:
q q

q q q q

Un modelo de renderizado uniforme para pantallas e impresoras. Un amplio conjunto de grficos primitivos geomtricos, como curvas, rectngulos, y elipses y un mecanismo para renderizar virtualmente cualquier forma geomtrica. Mecanismos para detectar esquinas de formas, texto e imgenes. Un modelo de composicin que proporciona control sobre cmo se renderizan los objetos solapados. Soporte de color mejorado que facilita su manejo. Soporte para imprimir documentos complejos.

Estos tpicos se explican en las siguiente pginas.

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Renderizado en Java 2D
r r

Contexto de Renderizado de Graphics2D Mtodos de renderizado de Graphics2D

Renderizado en Java 2D
El mecanismo de renderizado bsico es el mismo que en las versiones anteriores del JDK -- el sistema de dibujo controla cundo y cmo dibuja un programa. Cuando un componente necesita ser mostrado, se llama automticamente a su mtodo paint o update dentro del contexto Graphics apropiado. El API 2D de Java presenta java.awt.Graphics2D, un nuevo tipo de objeto Graphics. Graphics2D desciende de la clase Graphics para proporcionar acceso a las caractersticas avanzadas de renderizado del API 2D de Java. Para usar las caractersticas del API 2D de Java, tenemos que forzar el objeto Graphics pasado al mtodo de dibujo de un componente a un objeto Graphics2D.

public void Paint (Graphics g) { Graphics2D g2 = (Graphics2D) g; ... } Contexto de Renderizado de Graphics2D
Al conjunto de atributos de estado asociados con un objeto Graphics2D se le conoce como Contexto de Renderizado de Graphics2D. Para mostrar texto, formas o imgenes, podemos configurar este contexto y luego llamar a uno de los mtodos de renderizado de la clase Graphics2D, como draw o fill . Cmo muestra la siguiente figura, el contexto de renderizado de Graphics2D contiene varios atributos.

El estilo de lpiz que se aplica al exterior de una forma. Este atributo stroke nos permite dibujar lneas con cualquier tamao de punto y patrn de sombreado y aplicar finalizadores y decoraciones a la lnea.

El estilo de relleno que se aplica al interior de la forma. Este atributo paint nos permite rellenar formas con clores slidos, gradientes o patrones.

El estilo de composicin se utiliza cuando los objetos dibujados se solapan con objetos existentes.

La transformacin que se aplica durante el dibujado para convertir el objeto dibujado desde el espacio de usuario a las coordenadas de espacio del dispositivo. Tambin se pueden aplicar otras transformaciones opcionales como la traduccin, rotacin escalado, recortado, a travs de este atributo.

El Clip que restringe el dibujado al rea dentro de los bordes de la Shape se utiliza para definir el ra de recorte. Se puede usar cualquier Shape para definir un clip.

La fuente se usa para convertir cadenas de texto.

Punto de Renderizado que especifican las preferencias en cuanto a velocidad y calidad. Por ejemplo, podemos especificar si se debera usar antialiasing, si est disponible.

Para configurar un atributo en el contexto de renderizado de Graphics2D, se usan los mtodos set Attribute.
q q q q q q q

setStroke setPaint setComposite setTransform setClip setFont setRenderingHints

Cuando configuramos un atributo, se el pasa al objeto el atributo apropiado. Por ejemplo, para cambiar el atributo paint a un relleno de gradiente azul-gris, deberamos construir el objeto GradientPaint y luego llamar a setPaint.

gp = new GradientPaint(0f,0f,blue,0f,30f,green); g2.setPaint(gp);


Graphics2D contiene referencias a sus objetos atributos -- no son clonados. Si modificamos un objeto atributo que forma parte del contexto Graphics2D, necesitamos llamar al mtodo set para notificarlo al contexto. La modificacin de un atributo de un objeto durante el renderizado puede causar comportamientos impredecibles.

Mtodos de renderizado de Graphics2D


Graphics2D proporciona los siguientes mtodos generales de dibujado que pueden usarser para dibujar cualquier primitivo geomtrico, texto o imagen.
q q

draw--dibuja el exterior de una forma geomtrica primitiva usando los atributos stroke y paint. fill--dibuja cualquier forma geomtrica primitiva rellenado su interior con el color o patrn especificado por el atributo paint. drawString--dibuja cualquier cadena de texto. El atributo font se usa para convertir la fuente a glyphs que luego se rellenan con el color o patrn especificados por el atributo paint. drawImage--dibuja la imagen especificada.

Adems, Graphics2D soporta los mtodos de renderizado de Graphics para formas particulares, como drawOval y fillRect.

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Sistema de Coordenadas

Sistema de Coordenadas
El sistema 2D de Java mantiene dos espacios de coordenadas:
q q

El espacio de usuario es el espacio en que se especifican los grficos primitivos. El espacio de dispositivo es el sistema de coordenadas para un diopositivo de salida, como una pantalla, una ventana o una impresora.

El espacio de usuario es un sistema de coordenadas lgicas independiente del dispositivo: el espacio de coordenas que usan nuestros programas. Todos los geomtricos pasados a las rutinas Java 2D de renderizado se especifican en coordenadas de espacio de usuario. Cuando se utiliza la transformacin por defecto desde el espacio de usuario al espacio de dispositivo, el origen del espacio de usuario es la esquina superior izquierda del rea de dibujo del componente. La coordena X se incrementa hacia la derecha, y la coordena Y hacia abajo. El espacio de dispositivo es un sistema de coordenadas dependiente del dispositivo que vara de acuerdo a la fuente del dispositivo. Aunque el sistema de coordenas para una ventana o una pantalla podra ser muy distinto que para una impresora, estas diferencias son invisibles para los programas Java. Las conversiones necesarias entre el espacio de usuario y el espacio de dispositivo se realizan automticamente durante el dibujado.

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Formas 2D
r r r r

Formas Rectangulares QuadCurve2D y CubicCurve2D GeneralPath Areas

Formas 2D
Las clases del paquete java.awt.geom definen grficos primitivos comunes, como puntos, lneas, curvas, arcos, rectngulos y elipses. Clases en el paquete java.awt.geom Arc2D Area Ellipse2D QuadCurve2D RectangularShape RoundRectangle2D GeneralPath Rectangle2D

CubicCurve2D Line2D Dimension2D Point2D

Excepto para Point2D y Dimension2D, cada una de las otras clases geomtricas implementa el interface Shape, que proporciona un conjunto de mtodos comunes para describir e inspeccionar objetos geomtricos bi-dimensionales. Con estas clases podemos crear de forma virtual cualquiere forma geomtrica y dibujarla a travs de Graphics2D llamando al mtodo draw o al mtodo fill. Por ejemplo, las formas geomtricas del siguiente applet estn definidas usando los geomtricos bsicos de Java 2D. Si tienes curiosidad, el cdigo del programa est en ShapesDemo2D.java. La forma de dibujar y rellenar formas se describe en la siguiente leccin Mostrar Grficos con Graphics2D.

Formas Rectangulares
Los primitivos Rectangle2D, RoundRectangle2D, Arc2D, y Ellipse2D descienden del RectangularShape, que define mtodos para objetos Shape que pueden ser descritos por una caja rectngular. La geometra de un RectangularShape puede ser extrapolada desde un rectngulo que encierra completamente el exterior de la Shape.

QuadCurve2D y CubicCurve2D
La clase QuadCurve2D nos permite crear segmentos de curvas cuadrticos. Una curva cuadrtica est definida por dos puntos finales y un punto de control. La clase CubicCurve2D nos permite crear segmentos de curvas cbicos. Una curva cbica est definida por dos puntos finales y dos puntos de control. Las siguientes figuras muestran ejemplos de curvas cuadrticas y cbicas.

GeneralPath
La clase GeneralPath nos permite crear una curva arbitraria especificando una serie de posiciones a lo largo de los lmites de la forma. Estas posiciones pueden ser conectadas por segmentos de lnea, curvas cuadrticas o curvas cbicas. La siguiente figura puede ser creada con 3 segmentos de lnea y una curva cbica.

Areas
Con la clase Area podemos realizar operaciones boolenas, como uniones, intersecciones y substracciones, sobre dos objetos Shape cualesquiera. Esta tcnica, nos permite crear rpidamente objetos Shape complejos sin tener que describir cada lnea de segmento o cada curva.

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Texto en Java 2D
r r

Fuentes Distribucin de Texto

Texto en Java 2D
Cuando necesitemos mostrar texto, podemos usar uno de los componentes orientados a texto, como los componentes Como usar Labels o Usar Componentes de Texto de Swing. Cuando se utiliza un componente de texto, mucho del trabajo lo hacen por nosotros--por ejemplo, los objetos JTextComponent proporcionan soporte interno para chequeo de pulsaciones y para mostrar texto internacional. Si queremos mostrar una cadena de texto esttica, podemos dibujarla directamente a travs de Graphics2D usando el mtodo drawString. Para especificar la fuente, podemos usar el mtodo setFont de Graphics2D. Si queremos implementar nuestras propias rutinas de edicin de texto o necesitamos ms control sobre la distribuccin del texto que la que proporcionan los componentes de texto, podemos usar las clases del paquete java.awt.font.

Fuentes
Las formas que una fuente usa para representar los caracteres de una cadena son llamadas glyphs. Un caracter particular o una combinacin de caracteres podra ser representada como uno o ms glyphs. Por ejemplo, podra ser representado por dos glyphs, mientras que la ligadura fi podra ser representada por un slo glyph. Se puede pensar en una fuente como en una coleccin de glyphs. Una sola fuente podra tener muchas caras, como pesada, mdia, oblqua, gtica y regular, Todas las caras de una fuente tienen caractersticas tipogrficas similares y pueden ser reconocidas como miembros de la misma familia. En otras palabras, una coleccin de glyphs con un estilo particular forma una cara de fuente; y una coleccin de caras de fuentes forman una familia de fuentes; y el conjunto de familias de fuentes forman el juego de fuentes disponibles en el sistema. Cuando se utiliza el API 2D de Java, se especifican las fuentes usando un ejemplar de Font. Podemos determinar las fuentes disponibles en el sistema llamando al mtodo esttico GraphicsEnvironment.getLocalGraphicsEnvironment y preguntando al GraphicsEnvironment devuelto. El mtodo getAllFonts devuelve un array que contiene ejemplares Font para todas las fuentes disponibles en el sistema; getAvailableFontFamilyNames devuelve una lista de las familias de fuentes disponibles. GraphicsEnvironment tambin describe la coleccin de dispositivos de dibujo de la plataforma, como pantallas e impresoras, que un programa Java puede utilizar. Esta informacin es usada cuando el sistema realiza la conversin del espacio de usuario al espacio de dispositivo durante el dibujo. Nota: En el JDK 1.1, las fuentes se describan con nombres lgicos que eran mapeados en diferentes caras de fuentes, dependiendo de las fuentes que estaban disponibles en una plataforma particular. Por razones de compatibilidad, Graphics2D tambin soporta la especificacin de fuentes por el nombre lgico. Para obtener una lista de los nombres lgicos de la fuentes, se puede llamar a java.awt.Toolkit.getFontList.

Distribucin de Texto
Antes de poder mostrar el texto, debe ser distribuido para que los caracteres sean representados por los glyphs apropiados en las posiciones apropiadas. Si estamos usando Swing, podemos dejar que JLabel o JTextComponent manejen la distribucin de texto por nosotros. JTextComponent

soporta texto bidireccional y est diseada para manejar las necesidades de la mayora de las aplicaciones internacionales. Para ms informacin sobre el uso de los componentes de texto Swing, puedes ver Usar Componentes de Texto. Si no estamos usando un componente de texto Swing para mostrar el texto automticamente, podemos usar uno de los mecanismos de Java 2D para manejar la distribucin de texto.
q

Si queremos implementar nuestras propias rutinas de edicin de texto, podemos usar la clase TextLayout para manejar la distribucin de texto, iluminacin y deteccin de pulsacin. Las facilidades proporcionadas por TextLayout manejan muchos casos comunes, incluyendo cadenas con fuentes mezcladas, lenguajes mezclados y texto bidireccinal. Para ms informacin sobre TextLayout, puedes ver Manejar la disttribucin de Texto. Si queremos un control total sobre la forma y posicin de nuestro texto, podemos construir nuestro propio objeto GlyphVector usando Font y renderizando cada GlyphVector a travs de Graphics2D. Para ms informacin sobre la implementacin de nuestro propio mecanismo de distribucin de texto, puedes ver Implementar un Mecanismo Personalizado de Distribucin de Texto

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Imgenes

Imgenes
El API 2D de Java implementa un nuevo modelo de imagen que soporta la manipulacin de imgenes de resolucin fija almacenadas en memoria. Una nueva clase Image en el paquete java.awt.image, se puede usar BufferedImage, para manipular datos de una imagen recuperados desde un fichero o una URL. Por ejemplo, se puede usar un BufferedImage para implementar doble buffer -- los elementos grficos son dibujados fuera de la pantalla en el BufferedImage y luego son copiados a la pantalla a travs de llamadas al mtodo drawImage de Graphics2D. Las clases BufferedImage y BufferedImageOp tambin permiten realizar una gran variedad de operaciones de filtrado de imgenes como blur. El modelo de imagen productor/consumidor proporcionado en las versiones anteriores del JDK sigue siendo soportado por razones de compatibilidad.

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Impresin

Impresin
Todos los grficos del AWT y de Java 2D, incluidos los grficos compuestos y las imgenes, pueden ser dibujadas en una impresora usando el API de Java 2D. Este API proporciona caractersticas de composicin de documentos que nos permite realizar dichas operaciones como cambiar el orden de impresin de las pginas. Dibujar en la impresora es como dibujar en la pantalla. El sistema de impresin controla cuando se dibujan las pginas, como lo hace el sistema grfico de la pantalla cuando un componente se dibuja en la pantalla. Nuestra aplicacin proporciona al sistema de impresin la informacin sobre el documento a imprimir, y el sistema de impresin determina cuando necesita dibujar cada pgina. Cuando las pginas necesitan ser dibujadas, el sistema de impresin llama al mtodo print de la aplicacin con el contexto Graphics apropiado. Para usar las caractersticas del API 2D de Java en la impresin, debemos forzar el objeto Graphics a un objeto Graphics2D, igual que se hace cuando se dibuja en la pantalla.

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Mostrar Grficos con Graphics2D

Mostrar Grficos con Graphics2D


Esta leccin nos muestra cmo usar Graphics2D para mostrar grficos con lneas exteriores, estilos de relleno, transformacin de grficos mientras son dibujados, con restriccin de dibujo en un rea particular y generalmente controla la forma y aspecto de los grficos. Tambin aprenderemos cmo crear objetos complejos combinando algunos simples y cmo detectar cuando el usuario pulsa sobre un grfico primitivo. Estos tpicos se describen en las siguientes pginas.

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Punteado y Relleno de Grficos Primitivos


r r r r r r r r r

Dibujar Curvas Ejemplo: Quad Ejemplo: Cubic Dibujar formas arbitrarias Ejemplo: Odd_Shape Definir Estilos de lnea divertidos y Patrones de relleno. Estilos de Lnea Patrn de Relleno Ejemplo: StrokeAndFill

Punteado y Relleno de Grficos Primitivos


Cambiando el punteado y los atributos de dibujo en el contexto de Graphics2D, antes del dibujo, podemos fcilmente aplicar estilos divertidos de lneas y patrones de relleno para grficos primitivos. Por ejemplo, podemos dibujar una lnea punteada creando el objeto Stroke apropiado y llamando a setStroke para aadirlo al contexto Graphics2D antes de dibujar la lnea. De forma similar, podemos aplicar un relleno de gradiente a un Shape creando un objeto GradientPaint y aadiendo al contexto Graphics2D llamando a setPaint antes de dibujar la Shape. El siguiente applet demuestra cmo podemos dibujar formas geomtricas usando los mtodos Graphics2D draw y fill.

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecer en una nueva ventana del navegador. ShapesDemo2D.java contiene el cdigo completo de este applet. Cada una de las formas dibujadas por el applet est construida de geometras y est dibujada a

travs de Graphics2D. Las variables rectHeight y rectWidth de este ejemplo definen las dimensiones del espacio en que se dibuja cada forma, en pixels. La variables x e y cambian para cada forma para que sean dibujadas en formacin de parrilla.

// draw Line2D.Double g2.draw(new Line2D.Double(x, y+rectHeight-1, x + rectWidth, y));

// draw Rectangle2D.Double g2.setStroke(stroke); g2.draw(new Rectangle2D.Double(x, y, rectWidth, rectHeight)); // draw RoundRectangle2D.Double g2.setStroke(dashed); g2.draw(new RoundRectangle2D.Double(x, y, rectWidth, rectHeight, 10, 10)); // draw Arc2D.Double g2.setStroke(wideStroke); g2.draw(new Arc2D.Double(x, y, rectWidth, rectHeight, 90, 135, Arc2D.OPEN)); // draw Ellipse2D.Double g2.setStroke(stroke); g2.draw(new Ellipse2D.Double(x, y, rectWidth, rectHeight)); // draw GeneralPath (polygon) int x1Points[] = {x, x+rectWidth, x, x+rectWidth}; int y1Points[] = {y, y+rectHeight, y+rectHeight, y}; GeneralPath polygon = new GeneralPath(GeneralPath.WIND_EVEN_ODD, x1Points.length); polygon.moveTo(x1Points[0], y1Points[0]); for (int index = 1; index < x1Points.length; index++) { polygon.lineTo(x1Points[index], y1Points[index]); }; polygon.closePath(); g2.draw(polygon); // draw GeneralPath (polyline) int x2Points[] = {x, x+rectWidth, x, x+rectWidth}; int y2Points[] = {y, y+rectHeight, y+rectHeight, y}; GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, x2Points.length); polyline.moveTo (x2Points[0], y2Points[0]); for (int index = 1; index < x2Points.length; index++) { polyline.lineTo(x2Points[index], y2Points[index]); };

g2.draw(polyline); // fill Rectangle2D.Double (red) g2.setPaint(red); g2.fill(new Rectangle2D.Double(x, y, rectWidth, rectHeight)); // fill RoundRectangle2D.Double g2.setPaint(redtowhite); g2.fill(new RoundRectangle2D.Double(x, y, rectWidth, rectHeight, 10, 10)); // fill Arc2D g2.setPaint(red); g2.fill(new Arc2D.Double(x, y, rectWidth, rectHeight, 90, 135, Arc2D.OPEN)); // fill Ellipse2D.Double g2.setPaint(redtowhite); g2.fill (new Ellipse2D.Double(x, y, rectWidth, rectHeight)); // fill and stroke GeneralPath int x3Points[] = {x, x+rectWidth, x, x+rectWidth}; int y3Points[] = {y, y+rectHeight, y+rectHeight, y}; GeneralPath filledPolygon = new GeneralPath(GeneralPath.WIND_EVEN_ODD, x3Points.length); filledPolygon.moveTo(x3Points[0], y3Points[0]); for (int index = 1; index < x3Points.length; index++) { filledPolygon.lineTo(x3Points[index], y3Points[index]); }; filledPolygon.closePath(); g2.setPaint(red); g2.fill(filledPolygon); Observa que este ejemplo usa implementaciones de doble precision de las clases geomtricas. Donde sea posible, las implementaciones de los float y doble precisin de cada geomtrico estn proporcionados por clases internas.

Dibujar Curvas
Los applets Cubic y Quad demuestran como crear curvas cbicas y cuadrticas usando CubicCurve2D y QuadCurve2D. Estos applets tambin demuestran como se dibujan las curvas con respecto al posicionamiento de los puntos de control permitiendonos mover interactivamente tanto los puntos de control como los puntos finales.

Ejemplo: Quad
El applet Quad demuestra una curva cuadrtica, que es un segmento de curva que tiene dos puntos finales y un nico punto de control. El punto de control determina la forma de la curva controlando tanto el punto de control como los vectores tangenciales de los puntos finales.

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecer en una nueva ventana del navegador. Quad.java contiene el cdigo completo de este applet. Primero se crea una nueva curva cuadrtica con dos puntos finales y un punto de control y las posiciones de los puntos se seleccionan con respecto al tamao de la ventana.

QuadCurve2D.Double quad = new QuadCurve2D.Double(); Point2D.Double start, end, control; start = new Point2D.Double(); one = new Point2D.Double(); control = new Point2D.Double(); quad.setCurve(start, one, control); start.setLocation(w/2-50, h/2); end.setLocation(w/2+50, h/2); control.setLocation((int)(start.x)+50, (int)(start.y)-50);
Cada vez que el usuario mueva uno de los puntos, la curva se resetear.

quad.setCurve(start, control, end); Ejemplo: Cubic


El ejemplo Cubic muestra una curva cbica, que es un segmento de curva que tiene dos puntos finales y dos puntos de control. Cada punto de control determina la forma de la curva mediante el control de uno de los vectores tangenciales de un punto final. En el ejemplo Cubic, las cruces coloreadas se dibujan donde se encuentran los puntos de control y los puntos finales. El punto de control azul controla el punto final rojo y el punto de control verde controla el punto final magenta.

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecer en una nueva ventana del navegador. Cubic.java contiene el cdigo completo de este applet. Una curva cbica se crea con dos puntos finales y dos puntos de control y las localizaciones de los puntos se seleccionan con respecto al tamao de la ventana.

CubicCurve2D.Double cubic = new CubicCurve2D.Double(); Point2D.Double start, end, one, two; start = new Point2D.Double(); one = new Point2D.Double(); two = new Point2D.Double(); end = new Point2D.Double(); cubic.setCurve(start, one, two, end); ... start.setLocation(w/2-50, h/2); end.setLocation(w/2+50, h/2); one.setLocation((int)(start.x)+25, (int)(start.y)-25); two.setLocation((int)(end.x)-25, (int)(end.y)+25);
Como en el ejemplo Quad, la curva es reseteada cada vez que se mueven los puntos.

cubic.setCurve(start, one, two, end); Dibujar formas arbitrarias


El ejemplo ShapesDemo usa GeneralPath para hacer polgonos en forma de cristales, pero tambien podemos usar GeneralPath para hacer formas arbitrarias tanto con lneas rectas como curvas.

Ejemplo: Odd_Shape
El ejemplo Odd_Shape usa GeneralPath para crear formas arbitrarias en la seccin Formas.

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecer en una nueva ventana del navegador. Odd_Shape.java contiene el cdigo completo de este applet. El siguiente cdigo crea un nuevo GeneralPath y aade el primer punto al path.

GeneralPath oddShape = new GeneralPath(); ... x = w/2 + 50; y = h/2 - 25; x2 = x; y2 = y; oddShape.moveTo(x, y);

Despus de aadir el primer punto al path, se aaden tres lneas rectas.

x -= 100; oddShape.lineTo(x, y); y += 50; oddShape.lineTo(x, y); x += 100; oddShape.lineTo(x, y);


Finalmente, se aade una curva cbica.

x += 10; y -= 10; x1 = x - 20; y1 = y - 20; oddShape.curveTo(x, y, x1, y1, x2, y2); Definir Estilos de lnea divertidos y Patrones de relleno.
Probablemente habrs observado en el ejemplo anterior algunas de las formas tienen lneas punteadas o estn rellenas con gradientes de dos colores. Usando las clases Stroke y Paint de Java 2D, podemos fcilmente definir estilos de lnea divertidos y patrones de relleno.

Estilos de Lnea
Los estilos de lnea estn definidos por el atributo stroke en el contexto Graphics2D. Para seleccionar el atributo stroke podemos crear un objeto BasicStroke y pasarlo dentro del mtodo Graphics2D setStroke. Un objeto BasicStroke contiene informacin sobre la anchura de la lnea, estilo de uniones, estilos finales, y estilo de punteado. Esta informacin se usa cuando se dibuja un Shape con el mtodo draw. La anchura de lnea es la longitud de la lnea medida perpendicularmente a su trayectoria. La anchura de la lnea se especificada como un valor float en las unidades de coordenadas de usuario, que es equivalente a 1/72 pulgadas cuando se utiliza la transformacin por defecto. El estilo de unin es la decoracin que se aplica cuando se encuentran dos segmentos de lnea. BasicStroke soporta tres estilos de unin:. JOIN_BEVEL

JOIN_MITER JOIN_ROUND El estilo de finales es la decoracin que se aplica cuando un segmento de lnea termina. BasicStroke soporta tres estilos de finalizacin: CAP_BUTT CAP_ROUND CAP_SQUARE El estilo de punteado define el patrn de las secciones opacas y transparentes aplicadas a lo largo de la longitud de la lnea. Este estilo est definido por un array de punteado y una fase de punteado. El array de punteado define el patrn de punteado. Los elementos alternativos en el array representan la longitud del punteado y el espacio entre punteados en unidades de coordenadas de usuario.. El elemento 0 representa el primer punteado, el elemento 1 el primer espacio, etc. La fase de punteado es un desplazamiento en el patrn de punteado, tambin especificado en unidades de coordenadas de usuario. La fase de punteado indica que parte del patrn de punteado se aplica al principio de la lnea.

Patrn de Relleno
Los patrones de rellenos estn definidos por el atributo paint en el contexto Graphics2D. Para seleccionar el atributo paint, se crea un ejemplar de un objeto que implemente el interface Paint y se pasa dentro del mtodo Graphics2D setPaint.

Tres clases implementan el interface Paint: Color, GradientPaint, y TexturePaint . GradientPaint y TexturePaint son nuevas en el JDK 1.2. Para crear un GradientPaint, se especifica una posicin inicial y un color y una posicin final y otro color. El gradiente cambia proporcionalmente desde un color al otro a lo largo de la lnea que conecta las dos posiciones.

El patrn para una TexturePaint esta definido por un BufferedImage. Para crear un TexturePaint, se especifica una imagen que contiene el patrn y un rectngulo que se usa para replicar y anclar el patrn.

Ejemplo: StrokeAndFill
El applet StrokeAndFill permite al usuario seleccionar un grfico primitivo, un estilo de lnea, un estilo de dibujo y o bien puntear el exterior del objeto, rellenarlo con el dibujo seleccionado, o puntear el objeto en blanco y rellenar el dibujo con el dibujo seleccionado.

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecer en una nueva ventana del navegador. StrokeAndFill.java contiene el cdigo completo de este applet. Los primitivos son inicializados e introducidos en un array de objetos Shape. El siguiente cdigo crea un Rectangle y un Ellipse2D.Double y los introduce en el array shapes.

shapes[0] = new Rectangle(0, 0, 100, 100); shapes[1] = new Ellipse2D.Double(0.0, 0.0, 100.0, 100.0);
Para crear un objeto Shape desde una cadena de texto, primero debemos crear un objeto TextLayout desde el texto de la cadena.

TextLayout textTl = new TextLayout("Text", new Font("Helvetica", 1, 96), new FontRenderContext(null, false, false));

Las siguientes lneas transforman el TextLayout para que sea centrado en el origen y luego introduce el objeto Shape resultante de la llamda a getOutline dentro del array shapes.

AffineTransform textAt = new AffineTransform(); textAt.translate(0, (float)textTl.getBounds().getHeight()); shapes[2] = textTl.getOutline(textAt);


Podemos elegir un primitivo accediendo al ndice apropiado dentro del array shapes.

Shape shape = shapes[Transform.primitive.getSelectedIndex()];


Cmo se realiza el dibujo dependen de las opciones elegidas.
q

Cuando el usuario elige stroke, se llama a Graphics2D.draw para realizar el dibujo, Si se elige text como primitivo, las lneas son recuperadas y el dibujo se hace con el mtodo draw. Cuando el usuario elige fill, se llama a Graphics2D.fill o Graphics2D.drawString para realizar el dibujado. Cuando el usuario elige stroke and fill, se llama a fill o drawString para rellenar el Shape, y luego se llama a draw para dibujar la lnea exterior.

Nota: Para rellenar y puntear un grfico primitivo, necesitamos hacer dos llamadas separadas a mtodos: fill o drawString para rellenar el interior, y draw para dibujar el exterior. Los tres estilos de lnea usados en este ejemplo -- ancho, estrecho y punteado -- son ejemplares de BasicStroke.

// Sets the Stroke. ... case 0 : g2.setStroke(new BasicStroke(3.0f)); break; case 1 : g2.setStroke(new BasicStroke(8.0f)); break; case 2 : float dash[] = {10.0f}; g2.setStroke(new BasicStroke(3.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, dash, 0.0f)); break;
El estilo de punteado de este ejemplo tiene 10 unidades de punteado alternados con 10 unidades de espacio. El principio del patrn del punteado se aplica al principio de la lnea -- la fase de punteado es 0.0. En este ejemplo se usan tres estilos de dibujo -- slido, gradiente y polka. El dibujo de color slido es un ejemplar de Color, el gradiente un ejemplar de GradientPaint, y el patrn un ejemplar de TexturePaint.

// Sets the Paint. ... case 0 : g2.setPaint(Color.blue); break; case 1 : g2.setPaint(new GradientPaint(0, 0, Color.lightGray, w-250, h, Color.blue, false)); break; case 2 : BufferedImage bi = new BufferedImage(5, 5, BufferedImage.TYPE_INT_RGB); Graphics2D big = bi.createGraphics(); big.setColor(Color.blue); big.fillRect(0, 0, 5, 5); big.setColor(Color.lightGray); big.fillOval(0, 0, 5, 5); Rectangle r = new Rectangle(0,0,5,5); g2.setPaint(new TexturePaint(bi, r)); break;

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Transformar Formas, Texto e Imgenes


r

Ejemplo: Transform

Transformar Formas, Texto e Imgenes


Podemos modificar el atributo transform en el contexto Graphics2D para mover, rotar, escalar y modificar grficos primitivos mientras son dibujados. El atributo transform est definido por un ejemplar de AffineTransform. Graphics2D proporciona varios mtodos para cambiar el atributo transform. Podemos construir un nuevo AffineTransform y cambiar el atributo transform de Graphics2D llamando al mtodo setTransform. AffineTransform define los siguientes mtodos para hacer ms sencilla la construccin de nuevas transformaciones:
q q q q

getRotateInstance getScaleInstance getShearInstance getTranslateInstance

De forma alternativa podemos usar uno de los mtodos de transformacin de Graphics2D para modificar la transformacin actual. Cuando se llama a uno de esos mtodos de conveniencia, la transformacin resultante se concatena con la transformacin actual y es aplicada durante el dibujado.
q q q q

rotate--para especificar un ngulo de rotacin en radianes. scale--para especificar un factor de escala en direcciones x e y. shear--para especificar un factor de comparticin en direcciones x e y translate--para especificar un desplazamiento de movimiento en direcciones x e y

Tambin podemos construir directamente un AffineTransform y concatenarlo con la transformacin actual llamando al mtodo transform . El mtodo drawImage tambin est sobrecargado para permitirnos especificar un AffineTransform que es aplicado a la imagen a dibujar. Especificar un transform cuando se llama a drawImage no afecta al atributo transform de Graphics2D.

Ejemplo: Transform
El siguiente programa es el mismo que StrokeandFill, pero tambin permite al usuario elegir una transformacin para aplicarla al objeto selecciona cuando se dibuje.

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecer en una nueva ventana del navegador. Transform.java contiene el cdigo completo de este applet. Cuando se elige una opcin de transformacin, se modifica un ejemplar de AffineTransform y se concatena con una transformacin de movimiento que mueve la Shape hacia el centro de la ventana. La transformacin resultante se pasa al mtodo setTransform para seleccionar el atributo transform de Graphics2D

switch (Transform.trans.getSelectedIndex()){ case 0 : at.setToIdentity(); at.translate(w/2, h/2); break; case 1 : at.rotate(Math.toRadians(45)); break; case 2 : at.scale(0.5, 0.5); break; case 3 : at.shear(0.5, 0.0); break; ... AffineTransform toCenterAt = new AffineTransform(); toCenterAt.concatenate(at); toCenterAt.translate(-(r.width/2), -(r.height/2)); g2.setTransform(toCenterAt);

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Recortar la Regin de Dibujo


r r

Ejemplo: ClipImage Ejemplo: Starry

Recortar la Regin de Dibujo


Cualquier Shape puede usarse como un path de recortado que restringe las porciones del rea de dibujo que sern renderizadas. El path de recortado forma parte del contexto Graphics2D; para seleccionar el atributo clip, se llama a Graphics2D.setClip y se pasa a la Shape que define el path de recortado que queramos usar. Podemos reducir el path de recortado llamando al mtodo clip y pasndolo en otra Shape; el atributo clip se configura a la interseccin entre el clip actual y el Shape especificado.

Ejemplo: ClipImage
Este ejemplo anima un path de recortado para revelar diferentes porciones de una imagen:

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecer en una nueva ventana del navegador. ClipImage.java contiene todo el cdigo de este applet. El applet requiere el fichero de imagen clouds.jpg. El path de recortado est definido por la interseccin de una elipse y un rectngulo cuyas dimensiones son aleatorias. La elipse se pasa al mtodo setClip , y luego se llama al mtodo clip para seleccionar el path de recortado a la interseccin entre la elipse y el rectngulo.

private Ellipse2D ellipse = new Ellipse2D.Float(); private Rectangle2D rect = new Rectangle2D.Float(); ... ellipse.setFrame(x, y, ew, eh); g2.setClip(ellipse); rect.setRect(x+5, y+5, ew-10, eh-10); g2.clip(rect); Ejemplo: Starry
Un rea de recortado tambin puede crearse desde una cadena de texto existente. El siguiente ejemplo crea un TextLayout con la cadena The Starry Night. Luego, obtiene una lnea exterior del TextLayout. El mtodo TextLayout.getOutline devuelve un objeto Shape y un Rectangle creado a partir de los lmites del objeto Shape. Los lmites contienen todos los pixels que layout puede dibujar. El color en el contexto grfico se selecciona a azul y se dibuja la figura exterior de la

forma, como ilustran la siguiente imagen y el fragmento de cdigo.

FontRenderContext frc = g2.getFontRenderContext(); Font f = new Font("Helvetica", 1, w/10); String s = new String("The Starry Night"); TextLayout tl = new TextLayout(s, f, frc); AffineTransform transform = new AffineTransform(); Shape outline = textTl.getOutline(null); Rectangle r = outline.getBounds(); transform = g2.getTransform(); transform.translate(w/2-(r.width/2), h/2+(r.height/2)); g2.transform(transform); g2.setColor(Color.blue); g2.draw(outline);
Luego, se selecciona un rea de recortado en el contexto grfico usando el objeto Shape creado a partir de getOutline. La imagen starry.gif, que es una pintura famosa de Van Gogh, The Starry Night, se dibuja dentro de rea de recortado que empieza en la esquina inferior izquierda del objeto Rectangle.

g2.setClip(outline); g2.drawImage(img, r.x, r.y, r.width, r.height, this);

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecer en una nueva ventana del navegador. Starry.java contiene el cdigo completo de este programa. El applet requiere el fichero de imagen Starry.gif.

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Componer Grficos
r

Ejemplo: Composite

Componer Grficos
La clase AlphaComposite encapsula varios estilos de composicin, que determinan cmo se dibujan los objetos solapados. Un AlphaComposite tambin puede tener un valor alpha que especifica el grado de transparencia: alpha = 1.0 es totalmente opaco, alpha = 0.0 es totalmente transparente. AlphaComposite soporta la mayoria de los estandares de composicin como se muestra en la siguiente tabla. Source-over (SRC_OVER) Si los pixels del objeto que est siendo renderizado (la fuente) tienen la misma posicin que los pixels renderizados prviamente (el destino), los pixels de la fuente se renderizan sobre los pixels del destino. Source-in (SRC_IN) Si los pixels de la fuente y el destino se solapan, slo se renderizarn los pixels que haya en el rea solapada.

Source-out (SRC_OUT) Si los pixels de la fuente y el destino se solapan, slo se renderizarn los pixels que haya fuera del rea solapada. Los pixels que haya en el rea solapada se borrarn.

Destination-over (DST_OVER) Si los pixels de la fuente y del destino se solapan, slo se renderizarn los pixels de la fuente que haya fuera del rea solapada. Los pixels que haya en el rea solapada no se cambian.

Destination-in (DST_IN) Si los pixels de la fuente y del destino se solapan, el alpha de la fuente se aplica a los pixels del rea solapada del destino. Si el alpha = 1.0, los pixels del rea solapada no cambian; si alpha es 0.0 los pixels del rea solapada se borrarn. Destination-out (DST_OUT) Si los pixels de la fuente y del destino se solapan, se aplica el alpha de la fuente a los pixels del rea solapada del destino. Si el alpha = 1.0, los pixels del rea solapada no cambian; si alpha es 0.0 los pixels del rea solapada se borrarn.

Clear (CLEAR) Si los pixels de la fuente y del destino se solapan, los pixels del rea solapada se borrarn.

Para cambiar el estilo de composicin usado por Graphics2D, creamos un objeto AlphaComposite y lo pasamos al mtodo setComposite.

Ejemplo: Composite
Este programa ilustra los efectos de varias combinaciones de estilos de composicin y valores de alpha.

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecer en una nueva ventana del navegador. Composite.java contiene el cdigo completo de este applet. Se ha construido un nuevo objeto AlphaComposite ac llamando a AlphaComposite. getInstance y especificando las reglas de composicin deseadas.

AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC);
Cuando se selecciona una regla de composicin o un valor alpha, se llama de nuevo a AlphaComposite.getInstance, y el nuevo AlphaComposite se asigna a ac. El alpha seleccionado se aplica al valor alpha de cada pixel y se le pasa un segundo parmetro a AlphaComposite.getInstance.

ac = AlphaComposite.getInstance(getRule(rule), alpha);
El atributo composite se modifica pasando el objeto AlphaComposite a Graphics 2D setComposite. Los objetos son renderizados dentro de un BufferedImage y ms tarde se copian en la pantalla, por eso el atributo composite se configura con el contexto Graphics2D para el BufferedImage.

BufferedImage buffImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D gbi = buffImg.createGraphics(); ... gbi.setComposite(ac);

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Controlar la Calidad del Dibujo

Controlar la Calidad del Dibujo


Podemos usar el atributo 'rendering hint' de Graphics2D para especificar si queremos que los objetos sean dibujados tan rpido como sea posible o si preferimos que se dibujen con la mayor calidad posible. Para seleccionar o configurar el atributo 'rendering hint' en el contexto, Graphics2D podemos construir un objeto RenderingHints y pasarlo dentro de Graphics2D.setRenderingHints. Si slo queremos seleccionar un hint, podemos llamar a Graphics2D. setRenderingHint y especificar la pareja clave-valor para el hint que queremos seleccionar. (Estas parejas estn definidas en la clase RenderingHints.) Nota: No todas las plataformas soportan la modificacin del modo de dibujo, por eso el especificar los hints de dibujo no garantiza que sean utilizados. RenderingHints soporta los siguientes tipos de hints.
q q q q q q q q

Alpha interpolation--por defecto, calidad, o velocidad. Antialiasing--por defecto, on, u off Color rendering-por defecto, calidad, o velocidad Dithering--por defecto, activado o desactivado Fractional metrics--por defecto, on u off Interpolation--vecino ms cercano, bilinear, o bicbico Rendering--por defecto, calidad, o velocidad Text antialiasing--por defecto, on u off.

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Construir Formas Complejas desde Geomtricos Primitivos


r

Ejemplo: Areas

Construir Formas Complejas desde Geomtricos Primitivos


Construir un rea geomtrica (CAG) es el proceso de crear una nueva forma geomtrica realizando operaciones con las ya existentes. En el API Java 2D un tipo especial de Shape llamado Area soporta operaciones booleanas. Podemos construir un Area desde cualquier Shape . Area soporta la siguientes operaciones booleanas:

Unin

Subtraccin

Interseccin

Or-Exclusivo (XOR)

Ejemplo: Areas
En este ejemplo, los objetos Area construyen una forma de pera partiendo de varias elipses.

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecer en una nueva ventana del navegador. Pear.java contiene el cdigo completo de este applet. Las hojas son creadas realizando una intereseccin entre dos crculos solapados:

leaf = new Ellipse2D.Double(); ...

leaf1 = new Area(leaf); leaf2 = new Area(leaf); ... leaf.setFrame(ew-16, eh-29, 15.0, 15.0); leaf1 = new Area(leaf); leaf.setFrame(ew-14, eh-47, 30.0, 30.0); leaf2 = new Area(leaf); leaf1.intersect(leaf2); g2.fill(leaf1); ... leaf.setFrame(ew+1, eh-29, 15.0, 15.0); leaf1 = new Area(leaf); leaf2.intersect(leaf1); g2.fill(leaf2);
Los crculos solapados tambin se usan para cosntruir el rabo mediante una operacin de subtraccin:

stem = new Ellipse2D.Double(); ... stem.setFrame(ew, eh-42, 40.0, 40.0); st1 = new Area(stem); stem.setFrame(ew+3, eh-47, 50.0, 50.0); st2 = new Area(stem); st1.subtract(st2); g2.fill(st1);
El cuerpo de la pera est construido mediante una operacin unin de un crculo y un valo:

circle = new Ellipse2D.Double(); oval = new Ellipse2D.Double(); circ = new Area(circle); ov = new Area(oval); ... circle.setFrame(ew-25, eh, 50.0, 50.0); oval.setFrame(ew-19, eh-20, 40.0, 70.0); circ = new Area(circle); ov = new Area(oval); circ.add(ov); g2.fill(circ);

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Soportar Interaccin con el Usuario


r r

Ejemplo: ShapeMover Ejemplo: HitTestSample

Soportar Interaccin con el Usuario


Para permitir que el usuario interacte con los graficos que hemos dibujado, necesitamos poder determinar cuando el usuario pulsa sobre uno de ellos. El mtodo hit de Graphics2D proporciona una forma para determinar fcilmente si ha ocurrido una pulsacin de ratn sobre una Shape particular. De forma alternativa podemos obtener la posicin del click de ratn y llamar a contains sobre la Shape para determinar si el click ocurri dentro de los lmites de la Shape. Si estamos usando texto primitvo, podemos realizar una simple comprobacin obteniendo la lnea exterior de la Shape que corresponde al texto y luego llamando a hit o contains con esa Shape. El soporte de edicin de texto requiere una comprobacin mucho ms sofisticada. Si queremos permitir que el usuario edite el texto, generalmente deberamos usar uno de los componentes de texto editable de Swing. Si estamos trabajando con texto primitivo y estamos usando TextLayout para manejar la forma y posicin del texto, tambin podemos usar TextLayout para realizar la comprobacin para la edicin de texto. Para ms informacin puedes ver Java 2D Programmer's Guide.

Ejemplo: ShapeMover
Este applet permite al usuario arrastrar la Shape por la ventana del applet. La Shape se redibuja en cada nueva posicin del ratn para proporcionar informacin al usuario mientras la arrastra.

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecer en una nueva ventana del navegador. ShapeMover.java contiene el cdigo completo de este applet. Se llama al mtodo contains para determinar si el cursor est dentro de los lmites del rectngulo cuando se pulsa el botn. Si es as, se actualiza la posicin del rectngulo.

public void mousePressed(MouseEvent e){ last_x = rect.x - e.getX(); last_y = rect.y - e.getY(); if(rect.contains(e.getX(), e.getY())) updateLocation(e);

... public void updateLocation(MouseEvent e){ rect.setLocation(last_x + e.getX(), last_y + e.getY()); ... repaint();
Podras haber sobservado que redibujar la Shape en cada posicin del ratn es muy lento, porque el rectngulo relleno es renderizado cada vez que se mueve, Usando el doble buffer podemos eliminar este problema. Si estamos usando Swing, el dibujo usar doble buffer automticamente; si no es as tendremos que cambiar todo el cdigo de renderizado. El cdigo para una versin swing de este programa es SwingShapeMover.java . Para ejecutar la versin Swing, visita SwingShapeMover. Si no estamos usando Swing, el Ejemplo: BufferedShapeMover en la siguiente leccin nos muestra cmo podemos implementar el doble buffer usando un BufferedImage. Podemos dibujar en un BufferedImage y luego copiar la imagen en la pantalla.

Ejemplo: HitTestSample
Esta aplicacin ilustra la comprobacin de pulsaciones dibujando el cursor por defecto siempre que el usuario pulse sobre el TextLayout, como se muestra en la siguiente figura.

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecer en una nueva ventana del navegador. HitTestSample.java contiene el cdigo completo de este applet. El mtodo mouseClicked usa TextLayout.hitTestChar para devolver un objeto java.awt.font.TextHitInfo que contiene la posicin del click (el ndice de insercin) en el objeto TextLayout. La informacin devuelta por los mtodos de TextLayout, getAscent, getDescent y getAdvance se utiliza para calcular la posicin del origen del objeto TextLayout para que est centrado tanto horizontal como verticalmente.

... private Point2D computeLayoutOrigin() { Dimension size = getPreferredSize(); Point2D.Float origin = new Point2D.Float(); origin.x = (float) (size.width - textLayout.getAdvance()) / 2; origin.y = (float) (size.height - textLayout.getDescent() + textLayout.getAscent())/2; return origin; } ... public void paintComponent(Graphics g) { super.paintComponent(g); setBackground(Color.white); Graphics2D graphics2D = (Graphics2D) g; Point2D origin = computeLayoutOrigin(); graphics2D.translate(origin.getX(), origin.getY()); // Draw textLayout.

textLayout.draw(graphics2D, 0, 0); // Retrieve caret Shapes for insertionIndex. Shape[] carets = textLayout.getCaretShapes(insertionIndex); // Draw the carets. carets[0] is the strong caret and // carets[1] is the weak caret. graphics2D.setColor(STRONG_CARET_COLOR); graphics2D.draw(carets[0]); if (carets[1] != null) { graphics2D.setColor(WEAK_CARET_COLOR); graphics2D.draw(carets[1]); } } ... private class HitTestMouseListener extends MouseAdapter { /** * Compute the character position of the mouse click. */ public void mouseClicked(MouseEvent e) { Point2D origin = computeLayoutOrigin(); // Compute the mouse click location relative to // textLayout's origin. float clickX = (float) (e.getX() - origin.getX()); float clickY = (float) (e.getY() - origin.getY()); // Get the character position of the mouse click. TextHitInfo currentHit = textLayout.hitTestChar(clickX, clickY); insertionIndex = currentHit.getInsertionIndex(); // Repaint the Component so the new caret(s) will be displayed. hitPane.repaint(); }

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Trabajar con Texto y Fuentes


r r

Crear y Derivar Fuentes Dibujar Mltiples Lneas de Texto

Trabajar con Texto y Fuentes


Esta leccin muestra como determinar las fuentes disponibles en nuestro sistema, crear fuentes con atributos particulares, derivar nuevas fuentes modificando atributos de alguna fuente existente, y posicionar mltiples lneas de texto dentro de un componente. Estos tpicos se explican en las siguientes secciones.

Crear y Derivar Fuentes


Esta seccin ilustra cmo usar el GraphicsEnvironment para determinar las fuentes disponibles en nuestro sistema, cmo crear un objeto Font y como cambiar los atributos de la fuente de una cadena de texto.

Dibujar Mltiples Lneas de Texto


Esta seccin nos muestra cmo posicionar y dibujar un prrafo de texto con estilo usando TextLayout y LineBreakMeasurer.

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Crear y Derivar Fuentes


r

Ejemplo: FontSelection

Crear y Derivar Fuentes


Podemos mostrar una cadena de texto con cualquier fuente disponible en nuestro sistema, en cualquier estilo y tamao que elijamos. Para determinar las fuentes disponibles en nuestro sistema, podemos llamar al mtodo GraphicsEnvironment.getAvailableFontFamilyNames. Este mtodo devuelve un array de strings que contiene los nombres de familia de las fuentes disponibles. Se puede usar c ualquiera de las cadenas, junto con un argumento tamao y otro de estilo, para crear un nuevo objeto Font. Despus de crear un objeto Font, podemos cambiar su nombre de familia, su tamao o su estilo para crear una fuente personalizada.

Ejemplo: FontSelection
El siguiente applet nos permite cambiar la fuente, el tamao y el estilo del texto dibujado.

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecer en una nueva ventana del navegador. El cdigo completo del applet est en FontSelection.java . El mtodo getAvailableFontFamilyNames de GraphicsEnvironment devuelve los nombres de familia de todas las fuentes disponibles en nuestro sistema.

GraphicsEnvironment gEnv = GraphicsEnvironment.getLocalGraphicsEnvironment(); String envfonts[] = gEnv.getAvailableFontFamilyNames(); Vector vector = new Vector(); for ( int i = 1; i < envfonts.length; i++ ) { vector.addElement(envfonts[i]); }
El objeto Font inicial se crea con estilo Font.PLAIN y tamao 10. Los otros estilos disponibles son ITALIC, BOLD y BOLD+ITALIC.

Font thisFont; ... thisFont = new Font("Arial", Font.PLAIN, 10);


Un nuevo Font se crea a partir de un nombre de fuente, un estilo y un tamao.

public void changeFont(String f, int st, String si){ Integer newSize = new Integer(si); int size = newSize.intValue(); thisFont = new Font(f, st, size); repaint(); }
Para usar la misma familia de fuentes, pero cambiando uno o los dos atributos de estilo y tamao, podemos llamar a uno de los mtodos deriveFont. Para controlar la fuente utilizada para renderizar texto, podemos seleccionar el atributo font en el contexto Graphics2D antes de dibujarlo. Este atributo se selecciona pasando un objeto Font al mtodo setFont. En este ejemplo, el atributo font se configura para usar un objeto font recientemente construido y luego se dibuja la cadena de texto en el centro del componente usando la fuente especificada. En el mtodo paint, el atributo font del contecto Graphics2D se configura como el nuevo Font. La cadena se dibuja en el centro del componente con la nueva fuente.

g2.setFont(thisFont); String change = "Pick a font, size, and style to change me"; FontMetrics metrics = g2.getFontMetrics(); int width = metrics.stringWidth( change ); int height = metrics.getHeight(); g2.drawString( change, w/2-width/2, h/2-height/2 );
Nota: Debido al bug # 4155852, FontSelection podra no funcionar de forma apropiada con todos los nombres de fuentes devueltos por la llamada a getFontFamilyNames. La forma podra no corresponder con cambios en el tamao o el estilo y el texto podra no mostrarse cuando se selecionan algunos nombres de fuentes. En general, Courier y Helvetica funcionan bien. Mientras tanto, compruebalo peridicamente para ver si se han resuelto estos problemas.

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Dibujar Mltiples Lneas de Texto


r

Ejemplo: LineBreakSample

Dibujar Mltiples Lneas de Texto


Si tenemos un prrafo de texto con estilo que queremos que quepa dentro de una anchura especifica, podemos usar LineBreakMeasurer, que permite que el texto con estilo se rompa en lneas que caben dentro de un espacio visual. Como hemos aprendido en Mostrar Grficos con Graphics2D, un objeto TextLayout representa datos de caracteres con estilo, que no se pueden cambiar, pero tambin permite acceder a la informacin de distribucin. Los mtodos getAscent y getDescent de TextLayout devuelven informacin sobre la fuente usada para posicionar las lneas en el componente. El texto se almacena como un AttributedCharacterIterator para que los atributos de fuente y tamao de punto puedan ser almacenados con el texto.

Ejemplo: LineBreakSample
El siguiente applet posiciona un prrafo de texto con estilo dentro de un componente, usando LineBreakMeasurer, TextLayout y AttributedCharacterIterator.

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecer en una nueva ventana del navegador. El cdigo completo del applet est en LineBreakSample.java . El siguiente cdigo crea un bucle con la cadena vanGogh. El inicio y final del bucle se recupera y se crea una nueva lnea.

AttributedCharacterIterator paragraph = vanGogh.getIterator(); paragraphStart = paragraph.getBeginIndex(); paragraphEnd = paragraph.getEndIndex(); lineMeasurer = new LineBreakMeasurer(paragraph, new FontRenderContext(null, false, false));
El tamao de la ventana se utiliza para determinar dnde se debera romper la lnea y se crea un objeto TextLayout por cada lnea del prrafo.

Dimension size = getSize(); float formatWidth = (float) size.width;

float drawPosY = 0; lineMeasurer.setPosition(paragraphStart); while (lineMeasurer.getPosition() < paragraphEnd) { TextLayout layout = lineMeasurer.nextLayout(formatWidth); // Move y-coordinate by the ascent of the layout. drawPosY += layout.getAscent(); /* Compute pen x position. If the paragraph is rogth-to-left, we want to align the TextLayouts to the right edge of the panel. */ float drawPosX; if (layout.isRIGHTToLEFT()) { drawPosX = 0; } else { drawPosX = formatWidth - layout.getAdvance(); } // Draw the TextLayout at (drawPosX, drawPosY). layout.draw(graphics2D, drawPosX, drawPosY); // Move y-coordinate in preparation for next layout. drawPosY += layout.getDescent() + layout.getLeading(); }

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Mostrar y Manipular Imgenes


r r r

Modo Inmediato con BufferedImage Filtrado y BufferedImage Usar un BufferedImage para doble buffer

Mostrar y Manipular Imgenes


Esta leccin muestra cmo realizar operaciones de filtrado con BufferedImages y cmo usar un BufferedImage como un buffer fuera de pantalla.

Modo Inmediato con BufferedImage


Esta seccin describe el modelo de modo inmediato implementado en el API Java 2D y explica como BufferedImage permite la manipulacin de datos de imgenes.

Filtrado y BufferedImage
Esta seccin muestra cmo usar las clases BufferedImageOp para realizar operaciones de filtrado sobre BufferedImage.

Usar un BufferedImage para doble buffer


Esta seccin nos ensea cmo usar un BufferedImage como un buffer fuera de pantalla para aumentar el rendimiento de las imgenes.

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Modo Inmediato con BufferedImage

Modo Inmediato con BufferedImage


El modelo de imgenes "modo inmediato" permite manipular y mostrar imgenes de pixels mapeados cuyos datos estn almacenados en memoria. Podemos acceder a los datos de la imagen en una gran variedad de formatos y usar varios tipos de operaciones de filtrado para manipular los datos. BufferedImage es la clase clave del API del modo-inmediato. Esta clase maneja una imagen en memoria y proporciona mtodos para almacenar, interpretar y dibujar cada dato de pixel. Un BufferedImage puede ser renderizado en un contexto Graphics o on un contexto Graphics2D. Un BufferedImage es esencialmente un Image un buffer de datos accesible. Un BufferedImage tiene un ColorModel y un Raster de los datos de la imagen.

El ColorModel proporciona una interpretacin de color de los datos de los pixels de la imagen. El Raster representa las coordenadas rectangulares de la imagen, mantiene los datos de la imagen en memoria, y proporciona un mecanismo para crear mltiples subimagenes de un slo buffer de imagen. El Raster tambin proporciona mtodos para acceder a pixels especficos dentro de la imagen. Para ms informacin sobre como manipular directamente los datos de los pixels y escribir filtros para objetos BufferedImage, puedes ver el captulo Imaging de Java 2D Programmer's Guide.

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Filtrar un BufferedImage
r

Ejemplo: ImageOps

Filtrar un BufferedImage
El API Java 2D define varias operaciones de filtrado para objetos BufferedImage . Cada operacin de proceso de imgenes est incluida en una clase que implementa el interface BufferedImageOp. La manipulacin de imgenes se realiza en el mtodo filter. La clase BufferedImageOp en el API Java 2D soporta:
q q q q q q

Tranformacin afin. Escalado. Modificacin de Aspecto. Combinacin Linear de Bandas. Conversin de color. Convolucin.

Para filtrar un BufferedImage usando una de las clases de operacin de imagen, debemos

1. Constuir un ejemplar de una de las clases BufferedImageOp: AffineTransformOp, BandCombineOp, ColorConvertOp, ConvolveOp, LookupOp , o RescaleOp. 2. Llamar al mtodo de operacin filter, pasando en el BufferedImage que queremos filtrar y el BufferedImage donde queremos almacenar el resultado. Ejemplo: ImageOps
El siguiente applet ilustra el uso de cuatro operaciones de filtrado de imagenes: low-pass, sharpen, lookup, y rescale.

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecer en una nueva ventana del navegador. El cdigo completo del applet est en ImageOps.java. El applet usa estos dos ficheros de imagen: bld.jpg y boat.gif . El filtro sharpen se realiza usando un ConvolveOp. Convolucin es el proceso de hacer ms pesado el valor de cada pixel en una imagen con los valores de los pixels vecinos. La mayora de los algoritmos de filtrado espacial estan basados en las operaciones de convolucin. Para construir y aplicar este tipo de filtrado al BufferedImage, este ejemplo usa un cdigo similar al del siguiente fragmento.

public static final float[] SHARPEN3x3 = { 0.f, -1.f, 0.f, -1.f, 5.0f, -1.f, 0.f, -1.f, 0.f}; BufferedImage dstbimg = new BufferedImage(iw,ih,BufferedImage.TYPE_INT_RGB); Kernel kernel = new Kernel(3,3,SHARPEN3x3); ConvolveOp cop = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null); cop.filter(srcbimg,dstbimg);
El objeto Kernel define matemticamente cmo se ve afectada la salida de cada pixels en su rea inmediata. La definicin del Kernel determina el resultado del filtro. Para ms informacin sobre cmo trabaja el kernel con ConvolveOp puedes ver la seccin 'Image Processing and Enhancement' en Java 2D Programmer's Guide

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Usar un BufferedImage para Doble Buffer


r

Ejemplo: BufferedShapeMover

Usar un BufferedImage para Doble Buffer


Cuando un grfico es complejo o se usa repetidamente, podemos reducir el tiempo que tarda en mostrarse renderizndolo primero en un buffer fuera de pantalla y luego copiando el buffer en la pantalla. Esta tcnica, llamada doble buffer, se usa frecuentemente para animaciones. Nota: Cuando dibujamos sobre un componente Swing, ste utiliza automticamente el doble buffer. Un BufferedImage puede usarse fcilmente como un buffer fuera de pantalla. Para crear un BufferedImage cuyo espacio, color, profundidad y distribucin de pixels corresponden exactamente la ventana en la que son dibujados, se llama al mtodo Component. createImage. Si necesitamos control sobre el tipo de la imagen fuera de la pantalla, la transparencia, podemos construir directamente un objeto BufferedImage y usarlo como un buffer. Para dibujar dentro de una imagen almacenada, se llama al mtodo BufferedImage.createGraphics para obtener el objeto Graphics2D; luego se llama a los mtodos de dibujo apropiados del Graphics2D. Todo el API de dibujo de Java 2D puede usarse cuando se dibuja sobre un BufferedImage que est siendo utilizado como un buffer fuera de pantalla. Cuando estemos listos para copiar el BufferedImage en la pantalla, simplemente llamamos al mtodo drawImage sobre el Graphics2D de nuestro componente y pasarlo en BufferedImage.

Ejemplo: BufferedShapeMover
El siguiente applet permite al usuario arrastrar un rectngulo sobre la ventana del applet. En lugar de dibujar el rectngulo en cada posicin del cursor, para proporcionar informacin al usuario, se usa un BufferedImage como buffer fuera de la pantalla. Cuando se arrastra el rectngulo, es renderizado dentro del BufferedImage en cada nueva posicin y el BufferedImage se copia en la pantalla.

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecer en una nueva ventana del navegador. El cdigo completo del applet est en BufferedShapeMover.java. Aqu est el cdigo usado para renderizar en el BufferedImage y mostrar la imagen en la pantalla.

public void updateLocation(MouseEvent e){

rect.setLocation(last_x + e.getX(), last_y + e.getY()); ... repaint(); ... // In the update method... if(firstTime) { Dimension dim = getSize(); int w = dim.width; int h = dim.height; area = new Rectangle(dim); bi = (BufferedImage)createImage(w, h); big = bi.createGraphics(); rect.setLocation(w/2-50, h/2-25); big.setStroke(new BasicStroke(8.0f)); firstTime = false; } // Clears the rectangle that was previously drawn. big.setColor(Color.white); big.clearRect(0, 0, area.width, area.height); // Draws and fills the newly positioned rectangle // to the buffer. big.setPaint(strokePolka); big.draw(rect); big.setPaint(fillPolka); big.fill(rect); // Draws the buffered image to the screen. g2.drawImage(bi, 0, 0, this); }

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Imprimir en Java
r r r r

Introduccin a la Impresin en Java Imprimir los Contenidos de un Componente Mostrar el dilogo 'Page Setup' Imprimir una Coleccin de Pginas

Imprimir en Java
Esta leccin nos ensea cmo usar el API de Impresin de Java para imprimir desde nuestras aplicaciones Java. Aprenderemos cmo dibujar los contenidos de nuestros componentes a la impresora en lugar de al dispositivo de pantalla y como componer documentos de mltiples pginas. Esta leccin asume que has leido la primera leccin de esta ruta, Introduccin al API 2D de Java, y que ests familiarizado con el uso del contexto de dibujo Graphics2D.

Introduccin a la Impresin en Java


Esta seccin nos ofrece una introduccin al soporte de impresin del AWT y el API 2D de Java y describe el modelo de impresin de Java.

Imprimir los Contenidos de un Componente


Esta seccin nos ensea cmo crear un PrinterJob y cmo usar un Printable para imprimir los contenidos de un componente.

Mostrar el dilogo 'Page Setup'


Esta seccin describe el dilogo estandard de configuracin de pgina y nos ensea cmo usarla para permitir que el usuario configure un trabajo de impresin.

Imprimir una Coleccin de Pginas


Esta seccin ensea cmo configurar un Book para imprimir una coleccin de pginas que no tienen ni el mismo tamao ni orientacin.

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Introduccin a la Impresin en Java


r r r r

Job Control Imaging Printable Jobs Pageable Jobs

Introduccin a la Impresin en Java


El sistema controla totalmente el proceso de impresin, al igual que controla cmo y cundo pueden dibujar los programas, nuestras aplicaciones proporcionan informacin sobre el documento a imprimir, y el sistema de impresin determina cuando necesita renderizar cada pgina. Este modelo de impresin permite soportar una amplio rango de impresoras y de sistemas. Incluso permite al usuario imprimir en una impresora de bitmaps desde un ordenador que no tiene suficiente memoria o espacio en disco para contener el mapa de bits de una pgina completa. En esta situacin el sistema de impresin le pedir a nuesta aplicacin que renderize la pgina de forma repetida para que pueda ser imprimida como una serie de pequeas imgenes. Para soportar impresin, una apliacin necesita realizar dos tareas.
q q

Job control--manejar el trabajo de impresin Imaging--renderizar las pginas a imprimir

Job Control
Aunque el sistema controla todo el proceso de impresin, nuestra aplicacin tiene que obtener la oportunidad de configurar un PrinterJob. El PrinterJob , el punto clave del control del proceso de impresin, almacena las propiedades del trabajo de impresin, controla la visin de los dilogos de impresin y se usa para inicializar la impresin. Para dirigir el PrinterJob a travs del proceso de impresin, nuestra aplicacin necesita

1. Obtener un PrinterJob llamando a PrinterJob.getPrinterJob 2. Decirle al PrinterJob dnde est el cdigo de dibujo llamando a setPrintable o setPageable 3. Si se desea, mostrar los dilogos de configuracin de pgina e impresin llamando a pageDialog y printDialog 4. Iniciar la impresin llamando a print
El dibujo de pginas est controlado por el sistema de impresin a travs de llamadas al cdigo de imgenes de la aplicacin.

Imaging
Nuestra aplicacin debe poder renderizar cualquier pgina cuando el sistema de impresin lo pida. Este cdigo de renderizado est contenido en el mtodo print de un page painter--una clase que implementa el interface Printable. Nosotros implementamos print para renderizar el contenido de la pgina usando un Graphics o un Graphics2D. Podemos usar un nico 'page painter' para renderizar todas las pginas de un 'print job' o diferentes 'page painters' para los diferentes tipos de pginas. Cuando el sistema de impresin necesita renderizar una pgina, llama al mtodo print del 'page painter' apropiado. Cuando se usa un nico 'page painter', al 'print job' se le llama un printable job. Usar un 'printable job' es la forma ms sencilla de soportar impresin. Las operaciones de impresin ms complejas que usan mltiples 'page painters' son conocidas como pageable jobs. En un 'pageable job' se usa un ejemplar de una clase que implemente el interface Pageable para manejar los 'page painters'.

Printable Jobs

En un 'printable job' todas las pginas usan el mismo 'page painter' y PageFormat, que define el tamao y orientacin de la pgina a imprimir. Se le pide al 'page painter' que renderice cada pgina en orden indexado, empezando en la pgina con ndice 0. Al'page painter' se le podra pedir que renderizar una pgina varias veces antes de pedir la siguiente pgina. Por ejemplo, si un usuario quiere imprimir las pginas 2 y 3 de un documento, se le pide al 'page painter' que renderice las pginas con ndices 0,1 y 2 incluso aunque las dos primeras no sean impresas. Si se presenta un dilogo de impresin, no se mostrar el nmero de pginas, porque esa informacin no est disponible para el sistema de impresin, El 'page painter' informa al sistema de impresin cuando se alcanza el final del documento.

Pageable Jobs
Los 'pageable jobs' son tiles si nuestra aplicacin construye una representacin explcita de un documento, pgina por pgina. En un 'pageable job' diferentes pginas pueden usar diferentes 'page paintes' y PageFormats. El sistema de impresin puede pedir a los 'page painters' que rendericen las pginas en cualquier orden, incluso puede saltarse algunas. Por ejemplo si un usuario quiere imprimir las pginas 2 y 3 de un documento, slo se le pedir al 'page painter' que renderice las pginas con los ndices 1 y 2. Los distintos 'page painteres' de un 'pageable job' estn coordinados por una clase que implementa el interface Pageable, como un Book. Un Book representa una coleccin de pginas que pueden usar diferentes 'page painter' y que pueden variar en tamao y orientacin, Tambin podemos usar nuestra propia implementaciun del interface Pageable si Book no cumple con las necesidades de nuestra aplicacin.

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Imprimir los Contenidos de un Componente


r

Ejemplo: ShapesPrint

Imprimir los Contenidos de un Componente


Cualquier cosa que podamos dibujar en la pantalla tambin puede ser imprimida. Podemos fcilmente usar un 'printable job' para imprimir el contenido de un componente.

Ejemplo: ShapesPrint
En este ejmplo usamos el mismo cdigo de dibujo para mostrar e imprimir los contenidos de un componente. Cuando el usuario pulsa sobre el botn print, se crea un 'print job' y se llama a printDialog para mostrar el dilogo de impresin. Si el usuario contnua con el trabajo, el proceso de impresin se inicia, y el sistema de impresin llama a print cuando sea necesario renderizar el trabajo a la impresora.

ShapesPrint es el 'page painter'. Su mtodo print llama a drawShapes para realizar el dibujo del 'print job'. (Tambin se llama al mtodo drawShapes por parte de paintComponent para dibujar en la pantalla.)

public class ShapesPrint extends JPanel implements Printable, ActionListener { ... public int print(Graphics g, PageFormat pf, int pi) throws PrinterException {

if (pi >= 1) { return Printable.NO_SUCH_PAGE; } drawShapes((Graphics2D) g); return Printable.PAGE_EXISTS; } ... public void drawShapes(Graphics2D g2) { Dimension d = getSize(); int gridWidth = 400/6; int gridHeight = 300/2; int rowspacing = 5; int columnspacing = 7; int rectWidth = gridWidth - columnspacing; int rectHeight = gridHeight - rowspacing; ... int x = 85; int y = 87; ... g2.draw(new Rectangle2D.Double(x,y,rectWidth,rectHeight)); ...
El cdigo de control del trabajo est en el mtodo actionPerformed de ShapesPrint

public void actionPerformed(ActionEvent e) { if (e.getSource() instanceof JButton) { PrinterJob printJob = PrinterJob.getPrinterJob(); printJob.setPrintable(this); if (printJob.printDialog()) { try { printJob.print(); } catch (Exception ex) { ex.printStackTrace(); } } } }
Puedes encontrar el cdigo completo de este programa en ShapesPrint.java .

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Mostrar el Dilogo de Configuracin de Pgina

Mostrar el Dilogo de Configuracin de Pgina


Podemos permitir que el usuario especifique las caractersitcas de la pgina, como el tamao del papel y la orientacin, mostrndo el dilogo de Configuracin de Pgina. La informacin de la pgina se almacena en un objeto PageFormat. Al igual que el dilogo de Impresin, el dilogo de Configuracin de Pgina se muestra llamando un mtodo sobre el objeto PrinterJob, pageDialog. El dilogo de Configuracin de Pgina se inicializa usando el PageFormat pasado al mtodo pageDialog . Si el usuario pulsa sobre el botn OK del dilogo, se clona PageFormat, alterado para reflejar las selecciones del usuario, y luego retorna. si el usuario cancela el dilogo, pageDialog devuelve el original, sin modificar PageFormat. ShapesPrint podra fcilmente ser modificado para mostrar un dilogo de configuracin de pgina aadiendo una llamada a pageDialog despus de obtener el PrinterJob.

// Get a PrinterJob PrinterJob job = PrinterJob.getPrinterJob(); // Ask user for page format (e.g., portrait/landscape) PageFormat pf = job.pageDialog(job.defaultPage());

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Imprimir una Coleccin de Pginas


r

Ejemplo: SimpleBook

Imprimir una Coleccin de Pginas


Cuando se necesite ms control sobre las pginas individuales en un trabajo de impresin, podemos usar un 'pageable job' en lugar de un 'printable job'. La forma ms sencilla de manejar un 'pageable job' es utilizar la clase Book, que representa una coleccin de pginas.

Ejemplo: SimpleBook
El programa SimpleBook usa un Book para manejar dos 'page painters': PaintCover se utiliza para la cubierta, y PaintContent para la pgina de contenido. La cubierta se imprime en modo apaisado, mientras que el contenido se imprime en modo vertical. Una vez creado el Book, las pginas se aaden con el mtodo append. Cuando se aade una pgina a un Book, se necesita especificar el Printable y el PageFormat para usar con cada pgina.

// In the program's job control code... // Get a PrinterJob PrinterJob job = PrinterJob.getPrinterJob(); // Create a landscape page format PageFormat landscape = job.defaultPage(); landscape.setOrientation(PageFormat.LANDSCAPE); // Set up a book Book bk = new Book(); bk.append(new PaintCover(), job.defaultPage()); bk.append(new PaintContent(), landscape); // Pass the book to the PrinterJob job.setPageable(bk);
Se llama al mtodo setPageable sobre PrinterJob para decirle al sistema de control que utilice el Book para localizar el cdigo de dibujo adecuado. Puedes encontrar el programa completo en SimpleBook.java.

TutorJava recomienda...

Grficos con Java 2D

En esta pgina:
q

Problemas Ms Comunes en los Grficos en Java 2D

Problemas Ms Comunes en los Grficos en Java 2D


Problema: Puedo ejecutar applets Java2D con appletviewer, pero no funcionan con mi navegador. La consola Java del navegador dice: defn not found for java/awt/Graphics2D.
q

Necesitas descargar el Java Plugin 1.2 para ejecutar Swing y applets 2D en un navegador. Puedes descargar el plugin aqu.
http://java.sun.com/products/plugin/index.html Necesitars ajustar tus ficheros HTML para apuntar hacia el plugin. Aqu tienes una pgina con varios ejemplos, incluido un ejemplo 2D en la parte inferior: http://java.sun.com/products/plugin/1.2/demos/applets.html

Problema: Cmo puedo escribir sobre una imagen anterior? Nuestro problema es que nuestro applet muestra una imagen de un mapa, pero cuando se dibuja una lnea sobre el mapa, la lnea sobreescribe el mapa.
q

Deberas intentar dibujar tu imagen dentro de un BufferedImage. Luego, dibuja el BufferedImage dentro de un contexto Graphics2D y luego dibuja la lnea sobre el contexto Graphics2D un ejemplo de cdigo est en Map_Line.java Slo debes sustituir el nombre de tu imagen por images/bld.jpg. Para crear un BufferedImage desde un gif o jpeg, debes cargar tu fichero gif o jpeg en un objeto Image y luego dibujar el Image en el objeto BufferedImage. El siguiente fragmento de cdigo ilustra esto. Image img = getImage("picture.gif"); int width = img.getWidth(this); int height = img.getHeight(this); BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D biContext = bi.createGraphics(); biContext.drawImage(img, 0, 0, null);
getImage es un mtodo Applet. Si tienes una aplicacin, puedes usar.

Problema: Cmo creo un BufferedImage desde un fichero gif o jpeg?


q

Image img = Toolkit.getDefaultToolkit().getImage("picture.gif");


BufferedImage.TYPE_INT_RGB es uno de los muchos tipos de BufferedImage. Para ms informacin, puedes ver. http://java.sun.com/products/java-media/2D/forDevelopers/2Dapi/java/awt/image/BufferedImage.html Necesitas crear un contexto Graphics2D para el BufferedImage usando el mtodo createGraphics. Luego, puedes usar el mtodo drawImage de la clase Graphics2D para dibujar la imagen dentro del buffer. Problema: No puedo compilar el cdigo fuente de StrokeAndFill.java y Transform.java con jdk1.2beta4.
q

La implementacin de TextLayout.getOutline se cambi entre la beta4 y el JDK actual. La nueva implementacin slo toma un AffineTransform como argumento. Necesitas descargar el nuevo JDK para ejecutar el ejemplo. Usar los segmentos de lnea podra ser la forma ms sencilla. Pudes representar los segmentos de lnea rellenando un GeneralPath con ellos, o implementando Shape y PathIterator y leyendo los segmentos de lnea 'bajo demanda' para guardar el almacenamiento intermedio del objeto GeneralPath. Observa que podras analizar tu frmula para determinar si corresponde con curvas cbicas o cuadrticas. En el JDK 1.2 se aadi una clase llamada Graphics2D (ahora llamado Java 2 SDK). Esta clase desciende de Graphics. Hay dos mtodos drawString en Graphics2D que puedes utilizar. Si quieres rotar el texto, deberas usar Graphics2D en vez de Graphics por lo que podrs realizar rotaciones y otras transformaciones en tu contexto Graphics2D.
El ejemplo Transform en el tutorial de 2D no usa drawString para dibujar texto. Lo que sucede es que se crea un TextLayout desde la cadena "Text." El TextLayout nos permite crear un objeto Shape a partir del String obteniendo su forma exterior. Introducimos est Shape en el array de shapes, junto con las formas del rectngulo y de la elipse. Cuando dibujamos o rellenamos el Shape seleccionado del array de shapes, llamamos a g2.draw(Shape) o a g2.fill(Shape). Podras usar drawString para dibujar el texto en el contexto Graphics2D y luego llamar a g2.rotate (ngulo de rotacin). Esto rotar todo lo que hayamos introducido dentro del contexto Graphics2D. Por eso, podramos resetear el contexto g2 cada vez que querramos transformar una imagen particular o una parte del texto en el contexto de forma separada de otras cadenas que hayan sido renderizadas en el contexto g2.

Problema: Existe alguna forma de especificar una frmula para una lnea y dibujar un grfico de acuerdo a ella?
q

Problema: Cmo puedo aadir texto a un campo grfico en una cierta posicin?
q

Problema: He leido su comentario en la parte inferior de Crear y Derivar fuentes sobre el bug 4155852. Este bug ha sido cerrado sin ninguna accin. Es cierto que no se puede aplicar un estilo a una fuente como Arial?

El problema es que la correspondencia fuente-a-estilo no funciona de forma apropiada para fuentes fsicas (como Arial o Palatino). Slo se pueden aplicar estilos a las fuentes lgicas en este momento (como Dialog o SansSerif).
Como atajo hasta que se corrija el bug, podras hacer lo siguiente:

Font f = new Font("Palatino Bold", Font.PLAIN, 12);


en lugar de :

Font f = new Font("Palatino", Font.BOLD, 12);

/* * 1.2 version. */ import import import import java.awt.*; java.awt.event.*; java.awt.geom.*; javax.swing.*;

/* * This is like the FontDemo applet in volume 1, except that it * uses the Java 2D APIs to define and render the graphics and text. */ public class ShapesDemo2D extends JApplet { final static int maxCharHeight = 15; final static int minFontSize = 6; final final final final static static static static Color Color Color Color bg = Color.white; fg = Color.black; red = Color.red; white = Color.white;

final static BasicStroke stroke = new BasicStroke(2.0f); final static BasicStroke wideStroke = new BasicStroke(8.0f); final static float dash1[] = {10.0f}; final static BasicStroke dashed = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, dash1, 0.0f); Dimension totalSize; FontMetrics fontMetrics; public void init() { //Initialize drawing colors setBackground(bg); setForeground(fg); } FontMetrics pickFont(Graphics2D g2, String longString, int xSpace) { boolean fontFits = false; Font font = g2.getFont(); FontMetrics fontMetrics = g2.getFontMetrics(); int size = font.getSize(); String name = font.getName(); int style = font.getStyle(); while ( !fontFits ) { if ( (fontMetrics.getHeight() <= maxCharHeight) && (fontMetrics.stringWidth(longString) <= xSpace) ) { fontFits = true; } else { if ( size <= minFontSize ) { fontFits = true; } else { g2.setFont(font = new Font(name, style, --size)); fontMetrics = g2.getFontMetrics();

} } } return fontMetrics; } public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); Dimension d = getSize(); int gridWidth = d.width / 6; int gridHeight = d.height / 2; fontMetrics = pickFont(g2, "Filled and Stroked GeneralPath", gridWidth); Color fg3D = Color.lightGray; g2.setPaint(fg3D); g2.draw3DRect(0, 0, d.width - 1, d.height - 1, true); g2.draw3DRect(3, 3, d.width - 7, d.height - 7, false); g2.setPaint(fg); int int int int int x = 5; y = 7; rectWidth = gridWidth - 2*x; stringY = gridHeight - 3 - fontMetrics.getDescent(); rectHeight = stringY - fontMetrics.getMaxAscent() - y - 2;

// draw Line2D.Double g2.draw(new Line2D.Double(x, y+rectHeight-1, x + rectWidth, y)); g2.drawString("Line2D", x, stringY); x += gridWidth; // draw Rectangle2D.Double g2.setStroke(stroke); g2.draw(new Rectangle2D.Double(x, y, rectWidth, rectHeight)); g2.drawString("Rectangle2D", x, stringY); x += gridWidth; // draw RoundRectangle2D.Double g2.setStroke(dashed); g2.draw(new RoundRectangle2D.Double(x, y, rectWidth, rectHeight, 10, 10)); g2.drawString("RoundRectangle2D", x, stringY); x += gridWidth; // draw Arc2D.Double g2.setStroke(wideStroke); g2.draw(new Arc2D.Double(x, y, rectWidth, rectHeight, 90, 135, Arc2D.OPEN)); g2.drawString("Arc2D", x, stringY); x += gridWidth; // draw Ellipse2D.Double g2.setStroke(stroke); g2.draw(new Ellipse2D.Double(x, y, rectWidth, rectHeight)); g2.drawString("Ellipse2D", x, stringY); x += gridWidth; // draw GeneralPath (polygon) int x1Points[] = {x, x+rectWidth, x, x+rectWidth};

int y1Points[] = {y, y+rectHeight, y+rectHeight, y}; GeneralPath polygon = new GeneralPath(GeneralPath.WIND_EVEN_ODD, x1Points.length); polygon.moveTo(x1Points[0], y1Points[0]); for ( int index = 1; index < x1Points.length; index++ ) { polygon.lineTo(x1Points[index], y1Points[index]); }; polygon.closePath(); g2.draw(polygon); g2.drawString("GeneralPath", x, stringY); // NEW ROW x = 5; y += gridHeight; stringY += gridHeight; // draw GeneralPath (polyline) int x2Points[] = {x, x+rectWidth, x, x+rectWidth}; int y2Points[] = {y, y+rectHeight, y+rectHeight, y}; GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, x2Points.length); polyline.moveTo (x2Points[0], y2Points[0]); for ( int index = 1; index < x2Points.length; index++ ) { polyline.lineTo(x2Points[index], y2Points[index]); }; g2.draw(polyline); g2.drawString("GeneralPath (open)", x, stringY); x += gridWidth; // fill Rectangle2D.Double (red) g2.setPaint(red); g2.fill(new Rectangle2D.Double(x, y, rectWidth, rectHeight)); g2.setPaint(fg); g2.drawString("Filled Rectangle2D", x, stringY); x += gridWidth; // fill RoundRectangle2D.Double GradientPaint redtowhite = new GradientPaint(x,y,red,x+rectWidth, y,white); g2.setPaint(redtowhite); g2.fill(new RoundRectangle2D.Double(x, y, rectWidth, rectHeight, 10, 10)); g2.setPaint(fg); g2.drawString("Filled RoundRectangle2D", x, stringY); x += gridWidth; // fill Arc2D g2.setPaint(red); g2.fill(new Arc2D.Double(x, y, rectWidth, rectHeight, 90, 135, Arc2D.OPEN)); g2.setPaint(fg); g2.drawString("Filled Arc2D", x, stringY); x += gridWidth; // fill Ellipse2D.Double redtowhite = new GradientPaint(x,y,red,x+rectWidth, y,white); g2.setPaint(redtowhite); g2.fill (new Ellipse2D.Double(x, y, rectWidth, rectHeight)); g2.setPaint(fg); g2.drawString("Filled Ellipse2D", x, stringY); x += gridWidth;

// fill and stroke GeneralPath int x3Points[] = {x, x+rectWidth, x, x+rectWidth}; int y3Points[] = {y, y+rectHeight, y+rectHeight, y}; GeneralPath filledPolygon = new GeneralPath(GeneralPath.WIND_EVEN_ODD, x3Points.length); filledPolygon.moveTo(x3Points[0], y3Points[0]); for ( int index = 1; index < x3Points.length; index++ ) { filledPolygon.lineTo(x3Points[index], y3Points[index]); }; filledPolygon.closePath(); g2.setPaint(red); g2.fill(filledPolygon); g2.setPaint(fg); g2.draw(filledPolygon); g2.drawString("Filled and Stroked GeneralPath", x, stringY); } public static void main(String s[]) { JFrame f = new JFrame("ShapesDemo2D"); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} }); JApplet applet = new ShapesDemo2D(); f.getContentPane().add("Center", applet); applet.init(); f.pack(); f.setSize(new Dimension(550,100)); f.show(); } }

import import import import import import

java.awt.*; javax.swing.*; java.awt.event.*; java.applet.Applet; java.awt.geom.*; java.awt.image.BufferedImage;

public class Quad extends JApplet{ static protected JLabel label; QuadPanel quadPanel; public void init(){ //Initialize the layout. getContentPane().setLayout(new BorderLayout()); quadPanel = new QuadPanel(); quadPanel.setBackground(Color.white); getContentPane().add(quadPanel); label = new JLabel("Drag the points to adjust the curve."); getContentPane().add("South", label); } public static void main(String s[]) { JFrame f = new JFrame("Quad"); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} }); JApplet applet = new Quad(); f.getContentPane().add(applet, BorderLayout.CENTER); applet.init(); f.pack(); f.setSize(new Dimension(350,250)); f.setVisible(true); } } class QuadPanel extends JPanel implements MouseListener, MouseMotionListener{ BufferedImage bi; Graphics2D big; int x, y; Rectangle area, startpt, endpt, ctrl, rect; QuadCurve2D.Double quad = new QuadCurve2D.Double(); Point2D.Double start, end, control, point; boolean firstTime = true; boolean pressOut = false; public QuadPanel(){ setBackground(Color.white); addMouseMotionListener(this); addMouseListener(this); start = new Point2D.Double(); control = new Point2D.Double(); end = new Point2D.Double(); quad.setCurve(start, control, end); startpt = new Rectangle(0, 0, 8, 8); endpt = new Rectangle(0, 0, 8, 8); ctrl = new Rectangle(0, 0, 8, 8); } public void mousePressed(MouseEvent e){

x = e.getX(); y = e.getY(); if(startpt.contains(x, y)){ rect = startpt; point = start; x = startpt.x - e.getX(); y = startpt.y - e.getY(); updateLocation(e); } else if(endpt.contains(x, y)){ rect = endpt; point = end; x = endpt.x - e.getX(); y = endpt.y - e.getY(); updateLocation(e); } else if(ctrl.contains(x, y)){ rect = ctrl; point = control; x = ctrl.x - e.getX(); y = ctrl.y - e.getY(); updateLocation(e); } else { pressOut = true; } } public void mouseDragged(MouseEvent e){ if(!pressOut) { updateLocation(e); } } public void mouseReleased(MouseEvent e){ if(startpt.contains(e.getX(), e.getY())){ rect = startpt; point = start; updateLocation(e); } else if(endpt.contains(e.getX(), e.getY())){ rect = endpt; point = end; updateLocation(e); } else if(ctrl.contains(e.getX(), e.getY())){ rect = ctrl; point = control; updateLocation(e); } else { pressOut = false; } } public void mouseMoved(MouseEvent e){} public void mouseClicked(MouseEvent e){} public void mouseExited(MouseEvent e){} public void mouseEntered(MouseEvent e){}

public void updateLocation(MouseEvent e){ rect.setLocation((x + e.getX())-4, (y + e.getY())-4); point.setLocation(x + e.getX(), y + e.getY()); checkPoint(); quad.setCurve(start, control, end); repaint(); } public void paintComponent(Graphics g){ super.paintComponent(g); update(g); } public void update(Graphics g){ Graphics2D g2 = (Graphics2D)g; Dimension dim = getSize(); int w = dim.width; int h = dim.height; if(firstTime){ bi = (BufferedImage)createImage(w, h); big = bi.createGraphics(); start.setLocation(w/2-50, h/2); end.setLocation(w/2+50, h/2); control.setLocation((int)(start.x)+50, (int)(start.y)-50); startpt.setLocation((int)((start.x)-4), (int)((start.y)-4)); endpt.setLocation((int)((end.x)-4), (int)((end.y)-4)); ctrl.setLocation((int)((control.x)-4), (int)((control.y)-4)); quad.setCurve(start, control, end); big.setColor(Color.black); big.setStroke(new BasicStroke(5.0f)); big.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); area = new Rectangle(dim); firstTime = false; } // Clears the rectangle that was previously drawn. big.setColor(Color.white); big.clearRect(0, 0, area.width, area.height); // Draws and fills the newly positioned rectangle to the buffer. big.setPaint(Color.black); big.draw(quad); big.setPaint(Color.red); big.fill(startpt); big.setPaint(Color.magenta); big.fill(endpt); big.setPaint(Color.blue); big.fill(ctrl); // Draws the buffered image to the screen. g2.drawImage(bi, 0, 0, this); } /* * Checks if the rectangle is contained within the applet window. If the rectangle * is not contained withing the applet window, it is redrawn so that it is adjacent

* to the edge of the window and just inside the window. */ void checkPoint(){ if (area == null) { return; } if((area.contains(rect)) && (area.contains(point))){ return; } int new_x = rect.x; int new_y = rect.y; double new_px = point.x; double new_py = point.y; if((rect.x+rect.width)>area.getWidth()){ new_x = (int)area.getWidth()-(rect.width-1); } if(point.x > area.getWidth()){ new_px = (int)area.getWidth()-1; } if(rect.x < 0){ new_x = -1; } if(point.x < 0){ new_px = -1; } if((rect.y+rect.width)>area.getHeight()){ new_y = (int)area.getHeight()-(rect.height-1); } if(point.y > area.getHeight()){ new_py = (int)area.getHeight()-1; } if(rect.y < 0){ new_y = -1; } if(point.y < 0){ new_py = -1; } rect.setLocation(new_x, new_y); point.setLocation(new_px, new_py); } }

import import import import import import

java.awt.*; javax.swing.*; java.awt.event.*; java.applet.Applet; java.awt.geom.*; java.awt.image.BufferedImage;

public class Cubic extends JApplet{ static protected JLabel label; CubicPanel cubicPanel; public void init(){ //Initialize the layout. getContentPane().setLayout(new BorderLayout()); cubicPanel = new CubicPanel(); cubicPanel.setBackground(Color.white); getContentPane().add(cubicPanel); label = new JLabel("Drag the points to adjust the curve."); getContentPane().add("South", label); } public static void main(String s[]) { JFrame f = new JFrame("Cubic"); CubicPanel cubicPanel = new CubicPanel(); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} }); JApplet applet = new Cubic(); f.getContentPane().add(applet, BorderLayout.CENTER); applet.init(); f.setSize(new Dimension(350,250)); f.setVisible(true); } } class CubicPanel extends JPanel implements MouseListener, MouseMotionListener{ BufferedImage bi; Graphics2D big; int x, y; Rectangle area, startpt, endpt, ctrl1, ctrl2, rect; CubicCurve2D.Double cubic = new CubicCurve2D.Double(); Point2D.Double start, end, one, two, point; boolean firstTime = true; boolean pressOut = false; public CubicPanel(){ setBackground(Color.white); addMouseMotionListener(this); addMouseListener(this); start one = two = end = = new Point2D.Double(); new Point2D.Double(); new Point2D.Double(); new Point2D.Double();

cubic.setCurve(start, one, two, end); startpt = new Rectangle(0, 0, 8, 8); endpt = new Rectangle(0, 0, 8, 8); ctrl1 = new Rectangle(0, 0, 8, 8); ctrl2 = new Rectangle(0, 0, 8, 8); }

public void mousePressed(MouseEvent e){ x = e.getX(); y = e.getY(); if(startpt.contains(x, y)){ rect = startpt; point = start; x = startpt.x - e.getX(); y = startpt.y - e.getY(); updateLocation(e); } else if(endpt.contains(x, y)){ rect = endpt; point = end; x = endpt.x - e.getX(); y = endpt.y - e.getY(); updateLocation(e); } else if(ctrl1.contains(x, y)){ rect = ctrl1; point = one; x = ctrl1.x - e.getX(); y = ctrl1.y - e.getY(); updateLocation(e); } else if(ctrl2.contains(x, y)){ rect = ctrl2; point = two; x = ctrl2.x - e.getX(); y = ctrl2.y - e.getY(); updateLocation(e); } else { pressOut = true; } } public void mouseDragged(MouseEvent e){ if(!pressOut) { updateLocation(e); } } public void mouseReleased(MouseEvent e){ if(startpt.contains(e.getX(), e.getY())){ rect = startpt; point = start; updateLocation(e); } else if(endpt.contains(e.getX(), e.getY())){ rect = endpt; point = end; updateLocation(e); } else if(ctrl1.contains(e.getX(), e.getY())){ rect = ctrl1; point = one; updateLocation(e); } else if(ctrl2.contains(e.getX(), e.getY())){ rect = ctrl2; point = two;

updateLocation(e); } else { pressOut = false; } } public void mouseMoved(MouseEvent e){} public void mouseClicked(MouseEvent e){} public void mouseExited(MouseEvent e){} public void mouseEntered(MouseEvent e){} public void updateLocation(MouseEvent e){ rect.setLocation((x + e.getX())-4, (y + e.getY())-4); point.setLocation(x + e.getX(), y + e.getY()); checkPoint(); cubic.setCurve(start, one, two, end); repaint(); } public void paintComponent(Graphics g){ super.paintComponent(g); update(g); } public void update(Graphics g){ Graphics2D g2 = (Graphics2D)g; Dimension dim = getSize(); int w = dim.width; int h = dim.height; if(firstTime){ bi = (BufferedImage)createImage(w, h); big = bi.createGraphics(); start.setLocation(w/2-50, h/2); end.setLocation(w/2+50, h/2); one.setLocation((int)(start.x)+25, (int)(start.y)-25); two.setLocation((int)(end.x)-25, (int)(end.y)+25); startpt.setLocation((int)((start.x)-4), (int)((start.y)-4)); endpt.setLocation((int)((end.x)-4), (int)((end.y)-4)); ctrl1.setLocation((int)((one.x)-4), (int)((one.y)-4)); ctrl2.setLocation((int)((two.x)-4), (int)((two.y)-4)); cubic.setCurve(start, one, two, end); big.setColor(Color.black); big.setStroke(new BasicStroke(5.0f)); big.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); area = new Rectangle(dim); firstTime = false; } // Clears the rectangle that was previously drawn. big.setColor(Color.white); big.clearRect(0, 0, area.width, area.height); // Draws and fills the newly positioned rectangle to the buffer. big.setPaint(Color.black); big.draw(cubic); big.setPaint(Color.red);

big.fill(startpt); big.setPaint(Color.magenta); big.fill(endpt); big.setPaint(Color.blue); big.fill(ctrl1); big.setPaint(new Color(0, 200, 0)); big.fill(ctrl2); // Draws the buffered image to the screen. g2.drawImage(bi, 0, 0, this); } /* * Checks if the rectangle is contained within the applet window. If the rectangle * is not contained withing the applet window, it is redrawn so that it is adjacent * to the edge of the window and just inside the window. */ void checkPoint(){ if (area == null) { return; } if((area.contains(rect)) && (area.contains(point))){ return; } int new_x = rect.x; int new_y = rect.y; double new_px = point.x; double new_py = point.y; if((rect.x+rect.width)>area.getWidth()){ new_x = (int)area.getWidth()-(rect.width-1); } if(point.x > area.getWidth()){ new_px = (int)area.getWidth()-1; } if(rect.x < 0){ new_x = -1; } if(point.x < 0){ new_px = -1; } if((rect.y+rect.width)>area.getHeight()){ new_y = (int)area.getHeight()-(rect.height-1); } if(point.y > area.getHeight()){ new_py = (int)area.getHeight()-1; } if(rect.y < 0){ new_y = -1; } if(point.y < 0){ new_py = -1; } rect.setLocation(new_x, new_y); point.setLocation(new_px, new_py); } }

import import import import import

java.awt.*; java.awt.event.*; javax.swing.*; java.awt.geom.*; java.awt.image.BufferedImage;

public class Odd_Shape extends JApplet{ public void init(){ buildUI(getContentPane()); } public void buildUI(Container container) { setBackground(Color.white); OddPanel oddPanel = new OddPanel(); container.add(oddPanel, BorderLayout.CENTER); } public static void main(String s[]) { JFrame f = new JFrame("Odd_Shape"); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} }); Odd_Shape applet = new Odd_Shape(); applet.buildUI(f.getContentPane()); f.setSize(new Dimension(350,200)); f.setVisible(true); } } class OddPanel extends JPanel{ int x, y, x1, y1, x2, y2; GeneralPath oddShape; BufferedImage bi; Graphics2D big; boolean firstTime; Rectangle area; public OddPanel(){ oddShape = new GeneralPath(); firstTime = true; area = new Rectangle(); } public GeneralPath createPath(int x, int y) { x2 = x; y2 = y; oddShape.moveTo(x, y); x -= 100; oddShape.lineTo(x, y); y += 50; oddShape.lineTo(x, y); x += 100; oddShape.lineTo(x, y); x += 10; y -= 10; x1 = x - 20; y1 = y - 20; oddShape.curveTo(x, y, x1, y1, x2, y2); return oddShape; } public void paintComponent(Graphics g){

// super.paintComponent(g); Graphics2D g2 = (Graphics2D)g; if(firstTime){ Dimension dim = getSize(); int w = dim.width; int h = dim.height; x = w/2 + 50; y = h/2 - 25; oddShape = createPath(x, y); area = new Rectangle(w, h); bi = (BufferedImage)createImage(w, h); big = bi.createGraphics(); big.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); firstTime = false; } // Clears the shape that was previously drawn. big.setColor(Color.white); big.fillRect(0, 0, area.width, area.height); big.setColor(Color.magenta); big.setStroke(new BasicStroke(3.0f)); big.draw(oddShape); // Draws the buffered image to the screen. g2.drawImage(bi, 0, 0, this); } }

/* * @(#)StrokeandFill.java */ import import import import import import import import import import import

1.2 98/07/31

java.lang.Integer; java.awt.*; java.awt.event.*; java.awt.font.*; java.awt.geom.*; java.awt.image.*; java.awt.event.ActionListener; java.awt.event.ActionEvent; java.awt.event.ItemListener; java.awt.event.ItemEvent; javax.swing.*;

/* * This applet renders a Shape, selected by the user, using the Stroke and Paint attributes and rendering method * also selected by the user. */ public class StrokeAndFill extends JApplet implements ItemListener { JLabel primLabel, lineLabel, paintLabel, strokeLabel; ShapePanel display; static JComboBox primitive, line, paint, stroke; int index = 0; public static boolean no2D = false; public void init() { GridBagLayout layOut = new GridBagLayout(); getContentPane().setLayout(layOut); GridBagConstraints c = new GridBagConstraints(); c.weightx = 1.0; c.fill = GridBagConstraints.BOTH; primLabel = new JLabel(); primLabel.setText("Primitive"); Font newFont = getFont().deriveFont(1); primLabel.setFont(newFont); primLabel.setHorizontalAlignment(JLabel.CENTER); layOut.setConstraints(primLabel, c); getContentPane().add(primLabel); lineLabel = new JLabel(); lineLabel.setText("Lines"); lineLabel.setFont(newFont); lineLabel.setHorizontalAlignment(JLabel.CENTER); layOut.setConstraints(lineLabel, c); getContentPane().add(lineLabel); c.gridwidth = GridBagConstraints.RELATIVE; paintLabel = new JLabel(); paintLabel.setText("Paints"); paintLabel.setFont(newFont); paintLabel.setHorizontalAlignment(JLabel.CENTER); layOut.setConstraints(paintLabel, c); getContentPane().add(paintLabel); c.gridwidth = GridBagConstraints.REMAINDER; strokeLabel = new JLabel(); strokeLabel.setText("Rendering"); strokeLabel.setFont(newFont);

strokeLabel.setHorizontalAlignment(JLabel.CENTER); layOut.setConstraints(strokeLabel, c); getContentPane().add(strokeLabel); GridBagConstraints ls = new GridBagConstraints(); ls.weightx = 1.0; ls.fill = GridBagConstraints.BOTH; primitive = new JComboBox( new Object []{ "rectangle", "ellipse", "text"}); primitive.addItemListener(this); newFont = newFont.deriveFont(0, 14.0f); primitive.setFont(newFont); layOut.setConstraints(primitive, ls); getContentPane().add(primitive); line = new JComboBox( new Object []{ "thin", "thick", "dashed"}); line.addItemListener(this); line.setFont(newFont); layOut.setConstraints(line, ls); getContentPane().add(line); ls.gridwidth = GridBagConstraints.RELATIVE; paint = new JComboBox( new Object[]{ "solid", "gradient", "polka"}); paint.addItemListener(this); paint.setFont(newFont); layOut.setConstraints(paint, ls); getContentPane().add(paint); ls.gridwidth = GridBagConstraints.REMAINDER; stroke = new JComboBox( new Object[]{ "Stroke", "Fill", "Stroke & Fill"}); stroke.addItemListener(this); stroke.setFont(newFont); layOut.setConstraints(stroke, ls); getContentPane().add(stroke); GridBagConstraints sC = new GridBagConstraints(); sC.fill = GridBagConstraints.BOTH; sC.weightx = 1.0; sC.weighty = 1.0; sC.gridwidth = GridBagConstraints.REMAINDER; display = new ShapePanel(); layOut.setConstraints(display, sC); display.setBackground(Color.white); getContentPane().add(display); validate(); } public void itemStateChanged(ItemEvent e){ display.renderShape(); }

public static void main( String[] argv ) { if ( argv.length > 0 && argv[0].equals( "-no2d" ) ) { StrokeAndFill.no2D = true; } JFrame frame = new JFrame( "StrokeAndFill" ); frame.addWindowListener( new WindowAdapter(){ public void windowClosing( WindowEvent e ){ System.exit( 0 ); } }); JApplet applet = new StrokeAndFill(); frame.getContentPane().add( BorderLayout.CENTER, applet ); applet.init(); frame.setSize( 450, 250 ); frame.show(); } } class ShapePanel extends JPanel { BasicStroke bstroke = new BasicStroke(3.0f); int w, h; Shape shapes[] = new Shape[3]; public ShapePanel(){ setBackground(Color.white); shapes[0] = new Rectangle(0, 0, 100, 100); shapes[1] = new Ellipse2D.Double(0.0, 0.0, 100.0, 100.0); TextLayout textTl = new TextLayout("Text", new Font("Helvetica", 1, 96), new FontRenderContext(null, false, false)); AffineTransform textAt = new AffineTransform(); textAt.translate(0, (float)textTl.getBounds().getHeight()); shapes[2] = textTl.getOutline(textAt); } // Invokes the paint method. public void renderShape() { repaint(); } public void paintComponent (Graphics g) { super.paintComponent(g); if ( !StrokeAndFill.no2D ) { Graphics2D g2 = (Graphics2D) g; Dimension d = getSize(); w = d.width; h = d.height; int width, height; // Prints the initial instructions. String instruct = "Pick a primitive, line style, paint, and rendering method."; TextLayout thisTl = new TextLayout(instruct, new Font("Helvetica", 0, 10), g2.getFontRenderContext()); Rectangle2D bounds = thisTl.getBounds(); width = (int)bounds.getWidth(); thisTl.draw(g2, w/2-width/2, 20); Stroke oldStroke = g2.getStroke();

// Sets the Stroke. switch ( StrokeAndFill.line.getSelectedIndex() ) { case 0 : g2.setStroke(new BasicStroke(3.0f)); break; case 1 : g2.setStroke(new BasicStroke(8.0f)); break; case 2 : float dash[] = {10.0f}; g2.setStroke(new BasicStroke(3.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, dash, 0.0f)); break; } Paint oldPaint = g2.getPaint(); // Sets the Paint. switch ( StrokeAndFill.paint.getSelectedIndex() ) { case 0 : g2.setPaint(Color.blue); break; case 1 : g2.setPaint(new GradientPaint(0, 0, Color.lightGray, w-250, h, Color.blue, false)); break; case 2 : BufferedImage bi = new BufferedImage(5, 5, BufferedImage.TYPE_INT_RGB); Graphics2D big = bi.createGraphics(); big.setColor(Color.blue); big.fillRect(0, 0, 5, 5); big.setColor(Color.lightGray); big.fillOval(0, 0, 5, 5); Rectangle r = new Rectangle(0,0,5,5); g2.setPaint(new TexturePaint(bi, r)); break; } // Sets the Shape. Shape shape = shapes[StrokeAndFill.primitive.getSelectedIndex()]; Rectangle r = shape.getBounds(); // Sets the selected Shape to the center of the Canvas. AffineTransform saveXform = g2.getTransform(); AffineTransform toCenterAt = new AffineTransform(); toCenterAt.translate(w/2-(r.width/2), h/2-(r.height/2)); g2.transform(toCenterAt); // Determines whether to fill, stroke, or fill and stroke. switch ( StrokeAndFill.stroke.getSelectedIndex() ) { case 0 : g2.draw(shape); break; case 1 : g2.fill(shape); break; case 2 : Graphics2D tempg2 = g2; g2.fill(shape); g2.setColor(Color.darkGray); g2.draw(shape); g2.setPaint(tempg2.getPaint()); break; } g2.setTransform(saveXform); g2.setStroke(oldStroke); g2.setPaint(oldPaint); } else { g.drawRect(0, 0, 100, 100); } }}

/* * @(#)Transform.java */ import import import import import import import import import import import

1.2 98/07/31

java.lang.Integer; java.awt.*; java.awt.event.*; java.awt.font.*; java.awt.geom.*; java.awt.image.*; java.awt.event.ItemListener; java.awt.event.ItemEvent; java.awt.event.ActionListener; java.awt.event.ActionEvent; javax.swing.*;

/* * This applet renders a shape, selected by the user, with a paint,stroke, and rendering method, * also selected by the user. */ public class Transform extends JApplet implements ItemListener, ActionListener { JLabel primLabel, lineLabel, paintLabel, transLabel, strokeLabel; TransPanel display; static JComboBox primitive, line, paint, trans, stroke; JButton redraw; public static boolean no2D = false; public void init() { GridBagLayout layOut = new GridBagLayout(); getContentPane().setLayout(layOut); GridBagConstraints c = new GridBagConstraints(); c.weightx = 1.0; c.fill = GridBagConstraints.BOTH; primLabel = new JLabel(); primLabel.setText("Primitive"); Font newFont = getFont().deriveFont(1); primLabel.setFont(newFont); primLabel.setHorizontalAlignment(JLabel.CENTER); layOut.setConstraints(primLabel, c); getContentPane().add(primLabel); lineLabel = new JLabel(); lineLabel.setText("Lines"); lineLabel.setFont(newFont); lineLabel.setHorizontalAlignment(JLabel.CENTER); layOut.setConstraints(lineLabel, c); getContentPane().add(lineLabel); paintLabel = new JLabel(); paintLabel.setText("Paints"); paintLabel.setFont(newFont); paintLabel.setHorizontalAlignment(JLabel.CENTER); layOut.setConstraints(paintLabel, c); getContentPane().add(paintLabel); c.gridwidth = GridBagConstraints.RELATIVE; transLabel = new JLabel(); transLabel.setText("Transforms"); transLabel.setFont(newFont);

transLabel.setHorizontalAlignment(JLabel.CENTER); layOut.setConstraints(transLabel, c); getContentPane().add(transLabel); c.gridwidth = GridBagConstraints.REMAINDER; strokeLabel = new JLabel(); strokeLabel.setText("Rendering"); strokeLabel.setFont(newFont); strokeLabel.setHorizontalAlignment(JLabel.CENTER); layOut.setConstraints(strokeLabel, c); getContentPane().add(strokeLabel); GridBagConstraints ls = new GridBagConstraints(); ls.weightx = 1.0; ls.fill = GridBagConstraints.BOTH; primitive = new JComboBox( new Object []{ "rectangle", "ellipse", "text"}); primitive.addItemListener(this); newFont = newFont.deriveFont(0, 14.0f); primitive.setFont(newFont); layOut.setConstraints(primitive, ls); getContentPane().add(primitive); line = new JComboBox( new Object []{ "thin", "thick", "dashed"}); line.addItemListener(this); line.setFont(newFont); layOut.setConstraints(line, ls); getContentPane().add(line); paint = new JComboBox( new Object[]{ "solid", "gradient", "polka"}); paint.addItemListener(this); paint.setFont(newFont); layOut.setConstraints(paint, ls); getContentPane().add(paint); ls.gridwidth = GridBagConstraints.RELATIVE; trans = new JComboBox( new Object[]{ "Identity", "rotate", "scale", "shear"}); trans.addItemListener(this); trans.setFont(newFont); layOut.setConstraints(trans, ls); getContentPane().add(trans); ls.gridwidth = GridBagConstraints.REMAINDER; stroke = new JComboBox( new Object[]{ "Stroke", "Fill", "Stroke & Fill"}); stroke.addItemListener(this); stroke.setFont(newFont); layOut.setConstraints(stroke, ls); getContentPane().add(stroke);

GridBagConstraints button = new GridBagConstraints(); button.gridwidth = GridBagConstraints.REMAINDER; redraw = new JButton("Redraw"); redraw.addActionListener(this); redraw.setFont(newFont); layOut.setConstraints(redraw, button); getContentPane().add(redraw); GridBagConstraints tP = new GridBagConstraints(); tP.fill = GridBagConstraints.BOTH; tP.weightx = 1.0; tP.weighty = 1.0; tP.gridwidth = GridBagConstraints.REMAINDER; display = new TransPanel(); layOut.setConstraints(display, tP); display.setBackground(Color.white); getContentPane().add(display); validate(); } public void itemStateChanged(ItemEvent e){} public void actionPerformed(ActionEvent e) { display.setTrans(trans.getSelectedIndex()); display.renderShape(); } public static void main( String[] argv ) { if ( argv.length > 0 && argv[0].equals( "-no2d" ) ) { Transform.no2D = true; } JFrame frame = new JFrame( "Transform" ); frame.addWindowListener( new WindowAdapter(){ public void windowClosing( WindowEvent e ){ System.exit( 0 ); } }); JApplet applet = new Transform(); frame.getContentPane().add( BorderLayout.CENTER, applet ); applet.init(); frame.setSize( 550, 400 ); frame.show(); } } class TransPanel extends JPanel { AffineTransform at = new AffineTransform(); int w, h; Shape shapes[] = new Shape[3]; BufferedImage bi; boolean firstTime = true; public TransPanel(){ setBackground(Color.white); shapes[0] = new Rectangle(0, 0, 100, 100);

shapes[1] = new Ellipse2D.Double(0.0, 0.0, 100.0, 100.0); TextLayout textTl = new TextLayout("Text", new Font("Helvetica", 1, 96), new FontRenderContext(null, false, false)); AffineTransform textAt = new AffineTransform(); textAt.translate(0, (float)textTl.getBounds().getHeight()); shapes[2] = textTl.getOutline(textAt); } public void setTrans(int transIndex) { // Sets the AffineTransform. switch ( transIndex ) { case 0 : at.setToIdentity(); at.translate(w/2, h/2); break; case 1 : at.rotate(Math.toRadians(45)); break; case 2 : at.scale(0.5, 0.5); break; case 3 : at.shear(0.5, 0.0); break; } } public void renderShape() { repaint(); } public void paintComponent(Graphics g) { super.paintComponent(g); if ( !Transform.no2D ) { Graphics2D g2 = (Graphics2D) g; Dimension d = getSize(); w = d.width; h = d.height; // Prints out the intructions. String instruct = "Pick a primitive, line style, paint, transform,"; TextLayout thisTl = new TextLayout(instruct, new Font("Helvetica", 0, 10), g2.getFontRenderContext()); float width = (float)thisTl.getBounds().getWidth(); float height = (float)thisTl.getBounds().getHeight(); thisTl.draw(g2, w/2-width/2, 15); instruct = "and rendering method and click the Redraw button."; thisTl = new TextLayout(instruct, new Font("Helvetica", 0, 10), g2.getFontRenderContext()); width = (float)thisTl.getBounds().getWidth(); thisTl.draw(g2, w/2-width/2, height + 17); // Initialize the transform. if (firstTime) { at.setToIdentity(); at.translate(w/2, h/2); firstTime = false; } // Sets the Stroke. Stroke oldStroke = g2.getStroke(); switch ( Transform.line.getSelectedIndex() ) { case 0 : g2.setStroke(new BasicStroke(3.0f)); break; case 1 : g2.setStroke(new BasicStroke(8.0f)); break; case 2 : float dash[] = {10.0f}; g2.setStroke(new BasicStroke(3.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, dash, 0.0f)); break;

} // Sets the Paint. Paint oldPaint = g2.getPaint(); switch ( Transform.paint.getSelectedIndex() ) { case 0 : g2.setPaint(Color.blue);break; case 1 : g2.setPaint(new GradientPaint(0, 0, Color.lightGray, w-250, h, Color.blue, false)); break; case 2 : BufferedImage buffi = new BufferedImage(15, 15, BufferedImage.TYPE_INT_RGB); Graphics2D buffig = buffi.createGraphics(); buffig.setColor(Color.blue); buffig.fillRect(0, 0, 15, 15); buffig.setColor(Color.lightGray); buffig.translate((15/2)-(5/2), (15/2)-(5/2)); buffig.fillOval(0, 0, 7, 7); Rectangle r = new Rectangle(0,0,25,25); g2.setPaint(new TexturePaint(buffi, r)); break; }

// Sets the Shape. Shape shape = shapes[Transform.primitive.getSelectedIndex()]; Rectangle r = shape.getBounds(); // Sets the selected Shape to the center of the Canvas. AffineTransform saveXform = g2.getTransform(); AffineTransform toCenterAt = new AffineTransform(); toCenterAt.concatenate(at); toCenterAt.translate(-(r.width/2), -(r.height/2)); g2.transform(toCenterAt); // Sets the rendering method. switch ( Transform.stroke.getSelectedIndex() ) { case 0 : g2.draw(shape); break; case 1 : g2.fill(shape); break; case 2 : Graphics2D tempg2 = g2; g2.fill(shape); g2.setColor(Color.darkGray); g2.draw(shape); g2.setPaint(tempg2.getPaint()); break; } g2.setStroke(oldStroke); g2.setPaint(oldPaint); g2.setTransform(saveXform); } } }

/* * @(#)ClipImage.java 1.2 98/07/09 * * Copyright (c) 1998 Sun Microsystems, Inc. All Rights Reserved. * * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use, * modify and redistribute this software in source and binary code form, * provided that i) this copyright notice and license appear on all copies of * the software; and ii) Licensee does not utilize the software in a manner * which is disparaging to Sun. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * This software is not designed or intended for use in on-line control of * aircraft, air traffic, aircraft navigation or aircraft communications; or in * the design, construction, operation or maintenance of any nuclear * facility. Licensee represents and warrants that it will not use or * redistribute the Software for such purposes. */ import import import import import import import javax.swing.*; java.awt.*; java.awt.geom.*; java.awt.event.WindowEvent; java.awt.event.WindowListener; java.awt.event.WindowAdapter; java.awt.image.BufferedImage;

import java.net.URL; /** * Animated clipping of an image & shapes with alpha. */ public class ClipImage extends JApplet implements Runnable { private private private private private private private private private private private private private private private private private private Image img; final double OINC[] = {5.0, 3.0}; final double SINC[] = {5.0, 5.0}; double x, y; double ix = OINC[0]; double iy = OINC[1]; double iw = SINC[0]; double ih = SINC[1]; double ew, eh; // ellipse width & height GeneralPath p = new GeneralPath(); AffineTransform at = new AffineTransform(); BasicStroke bs = new BasicStroke(20.0f); Arc2D arc = new Arc2D.Float(); Ellipse2D ellipse = new Ellipse2D.Float(); RoundRectangle2D roundRect = new RoundRectangle2D.Float(); Rectangle2D rect = new Rectangle2D.Float(); Color redBlend = new Color(255, 0, 0, 120); Color greenBlend = new Color(0, 255, 0, 120);

private private private private

Thread thread; BufferedImage offImg; int w, h; boolean newBufferedImage;

public void init() { setBackground(Color.white); img = getImage(getURL("images/clouds.jpg")); try { MediaTracker tracker = new MediaTracker(this); tracker.addImage(img, 0); tracker.waitForID(0); } catch ( Exception e ) {} } public void drawDemo(Graphics2D g2) { if ( newBufferedImage ) { x = Math.random()*w; y = Math.random()*h; ew = (Math.random()*w)/2; eh = (Math.random()*h)/2; } x += ix; y += iy; ew += iw; eh += ih; if ( ew > w/2 ) { ew = w/2; iw = Math.random() * -w/16 - 1; } if ( ew < w/8 ) { ew = w/8; iw = Math.random() * w/16 + 1; } if ( eh > h/2 ) { eh = h/2; ih = Math.random() * -h/16 - 1; } if ( eh < h/8 ) { eh = h/8; ih = Math.random() * h/16 + 1; } if ( (x+ew) > w ) { x = (w - ew)-1; ix = Math.random() * -w/32 - 1; } if ( x < 0 ) { x = 2; ix = Math.random() * w/32 + 1; } if ( (y+eh) > h ) { y = (h - eh)-2; iy = Math.random() * -h/32 - 1; } if ( y < 0 ) { y = 2; iy = Math.random() * h/32 + 1; } ellipse.setFrame(x, y, ew, eh); g2.setClip(ellipse);

rect.setRect(x+5, y+5, ew-10, eh-10); g2.clip(rect); g2.drawImage(img, 0, 0, w, h, this); p.reset(); p.moveTo(- w / p.lineTo(+ w / p.lineTo(- w / p.lineTo(+ p.lineTo(+ w / p.closePath(); 2.0f, - h 2.0f, - h 4.0f, + h 0.0f, 4.0f, + h / / / / 8.0f); 8.0f); 2.0f); h / 2.0f); 2.0f);

at.setToIdentity(); at.translate(w*.5f, h*.5f); g2.transform(at); g2.setStroke(bs); g2.setPaint(redBlend); g2.draw(p); at.setToIdentity(); g2.setTransform(at); g2.setPaint(greenBlend); for ( int yy = 0; yy < h; yy += 50 ) { for ( int xx = 0, i=0; xx < w; i++, xx += 50 ) { switch ( i ) { case 0 : arc.setArc(xx, yy, 25, 25, 45, 270, Arc2D.PIE); g2.fill(arc); break; case 1 : ellipse.setFrame(xx, yy, 25, 25); g2.fill(ellipse); break; case 2 : roundRect.setRoundRect(xx, yy, 25, 25, 4, 4); g2.fill(roundRect); break; case 3 : rect.setRect(xx, yy, 25, 25); g2.fill(rect); i = -1; } } } } public Graphics2D createDemoGraphics2D(Graphics g) { Graphics2D g2 = null; if ( offImg == null || offImg.getWidth() != w || offImg.getHeight() != h ) { offImg = (BufferedImage) createImage(w, h); newBufferedImage = true; } if ( offImg != null ) { g2 = offImg.createGraphics(); g2.setBackground(getBackground()); } // .. set attributes .. g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

// .. clear canvas .. g2.clearRect(0, 0, w, h); return g2; } public void paint(Graphics g) { w = getWidth(); h = getHeight(); if ( w <= 0 || h <= 0 ) return; Graphics2D g2 = createDemoGraphics2D(g); drawDemo(g2); g2.dispose(); if ( offImg != null && isShowing() ) { g.drawImage(offImg, 0, 0, this); } newBufferedImage = false; } public void start() { thread = new Thread(this); thread.start(); } public synchronized void stop() { thread = null; } public void run() { Thread me = Thread.currentThread(); while ( thread == me && isShowing() ) { Graphics g = getGraphics(); paint(g); g.dispose(); thread.yield(); } thread = null; } protected URL getURL(String filename) { URL codeBase = this.getCodeBase(); URL url = null; try { url = new URL(codeBase, filename); } catch (java.net.MalformedURLException e) { System.out.println("Couldn't create image: " + "badly specified URL"); return null; } return url;

} public static void main(String s[]) { final ClipImage demo = new ClipImage(); WindowListener l = new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} public void windowDeiconified(WindowEvent e) { demo.start();} public void windowIconified(WindowEvent e) { demo.stop();} }; JFrame f = new JFrame("Java 2D Demo - ClipImage"); f.addWindowListener(l); f.getContentPane().add("Center", demo); f.setSize(new Dimension(400,300)); f.show(); demo.start(); } }

import import import import import

javax.swing.*; java.awt.*; java.awt.event.*; java.awt.geom.*; java.awt.font.*;

import java.net.URL; public class Starry extends JApplet { static String starryFile = "images/Starry.gif"; public void init() { Image starry = getImage(getURL(starryFile)); StarPanel starPanel = new StarPanel(starry); getContentPane().add(starPanel, BorderLayout.CENTER); } protected URL getURL(String filename) { URL codeBase = this.getCodeBase(); URL url = null; try { url = new URL(codeBase, filename); } catch (java.net.MalformedURLException e) { System.out.println("Couldn't create image: " + "badly specified URL"); return null; } return url; } public static void main(String[] args) { Image starImage = Toolkit.getDefaultToolkit().getImage( Starry.starryFile); StarPanel starPanel = new StarPanel(starImage); JFrame f = new JFrame("Starry"); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} }); f.getContentPane().add(starPanel, BorderLayout.CENTER); f.setSize(new Dimension(550, 200)); f.setVisible(true); } } class StarPanel extends JPanel { Image img; int w, h; public StarPanel(Image img) { this.img = img; } public void paintComponent(Graphics g) { super.paintComponent(g); setBackground(Color.white); w = getSize().width; h = getSize().height; Graphics2D g2;

g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); FontRenderContext frc = g2.getFontRenderContext(); Font f = new Font("Helvetica", 1, w/10); String s = new String("The Starry Night"); TextLayout textTl = new TextLayout(s, f, frc); AffineTransform transform = new AffineTransform(); Shape outline = textTl.getOutline(null); Rectangle r = outline.getBounds(); transform = g2.getTransform(); transform.translate(w/2-(r.width/2), h/2+(r.height/2)); g2.transform(transform); g2.setColor(Color.blue); g2.draw(outline); g2.setClip(outline); g2.drawImage(img, r.x, r.y, r.width, r.height, this); } }

/* * @(#)Composite.java */ import import import import import import

1.2 98/07/31

java.lang.Integer; java.awt.*; java.awt.event.*; java.awt.font.*; java.awt.geom.*; java.awt.image.*;

import java.awt.event.ItemListener; import java.awt.event.ItemEvent; import javax.swing.*; /* * This applet renders an ellipse overlapping a rectangle with the compositing rule and * alpha value selected by the user. */ public class Composite extends JApplet implements ItemListener { CompPanel comp; JLabel alphaLabel, rulesLabel; JComboBox alphas, rules; String alpha = "1.0"; int rule = 0; // Initializes the layout of the components. public void init() { GridBagLayout layOut = new GridBagLayout(); getContentPane().setLayout(layOut); GridBagConstraints l = new GridBagConstraints(); l.weightx = 1.0; l.fill = GridBagConstraints.BOTH; l.gridwidth = GridBagConstraints.RELATIVE; alphaLabel = new JLabel(); alphaLabel.setText("Alphas"); Font newFont = getFont().deriveFont(1); alphaLabel.setFont(newFont); alphaLabel.setHorizontalAlignment(JLabel.CENTER); layOut.setConstraints(alphaLabel, l); getContentPane().add(alphaLabel); GridBagConstraints c = new GridBagConstraints(); getContentPane().setLayout(layOut); l.gridwidth = GridBagConstraints.REMAINDER; rulesLabel = new JLabel(); rulesLabel.setText("Rules"); newFont = getFont().deriveFont(1); rulesLabel.setFont(newFont); rulesLabel.setHorizontalAlignment(JLabel.CENTER); layOut.setConstraints(rulesLabel, l); getContentPane().add(rulesLabel); GridBagConstraints a = new GridBagConstraints(); a.gridwidth = GridBagConstraints.RELATIVE; a.weightx = 1.0; a.fill = GridBagConstraints.BOTH; alphas = new JComboBox(); layOut.setConstraints(alphas, a); alphas.addItem("1.0"); alphas.addItem("0.75");

alphas.addItem("0.50"); alphas.addItem("0.25"); alphas.addItem("0.0"); alphas.addItemListener(this); getContentPane().add(alphas); a.gridwidth = GridBagConstraints.REMAINDER; rules = new JComboBox(); layOut.setConstraints(rules, a); rules.addItem("SRC"); rules.addItem("DST_IN"); rules.addItem("DST_OUT"); rules.addItem("DST_OVER"); rules.addItem("SRC_IN"); rules.addItem("SRC_OVER"); rules.addItem("SRC_OUT"); rules.addItem("CLEAR"); rules.addItemListener(this); getContentPane().add(rules); GridBagConstraints fC = new GridBagConstraints(); fC.fill = GridBagConstraints.BOTH; fC.weightx = 1.0; fC.weighty = 1.0; fC.gridwidth = GridBagConstraints.REMAINDER; comp = new CompPanel(); layOut.setConstraints(comp, fC); getContentPane().add(comp); validate(); } /* * Detects a change in either of the Choice components. Resets the variable corresponding * to the Choice whose state is changed. Invokes changeRule in CompPanel with the current * alpha and composite rules. */ public void itemStateChanged(ItemEvent e){ if ( e.getStateChange() != ItemEvent.SELECTED ) { return; } Object choice = e.getSource(); if ( choice == alphas ) { alpha = (String)alphas.getSelectedItem(); } else { rule = rules.getSelectedIndex(); } comp.changeRule(alpha, rule); } public static void main(String s[]) { JFrame f = new JFrame("Composite"); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} }); JApplet applet = new Composite(); f.getContentPane().add("Center", applet); applet.init(); f.pack(); f.setSize(new Dimension(300,300)); f.show();

} } class CompPanel extends JPanel { AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC); float alpha = 1.0f; public CompPanel(){} // Resets the alpha and composite rules with selected items. public void changeRule(String a, int rule) { alpha = Float.valueOf(a).floatValue(); ac = AlphaComposite.getInstance(getRule(rule), alpha); repaint(); } // Gets the requested compositing rule. public int getRule(int rule){ int alphaComp = 0; switch ( rule ) { case 0: alphaComp = AlphaComposite.SRC; break; case 1: alphaComp = AlphaComposite.DST_IN; break; case 2: alphaComp = AlphaComposite.DST_OUT; break; case 3: alphaComp = AlphaComposite.DST_OVER; break; case 4: alphaComp = AlphaComposite.SRC_IN; break; case 5: alphaComp = AlphaComposite.SRC_OVER; break; case 6: alphaComp = AlphaComposite.SRC_OUT; break; case 7: alphaComp = AlphaComposite.CLEAR; break; } return alphaComp; } public void paintComponent(Graphics g) { super.paintComponent( g ); Graphics2D g2 = (Graphics2D) g; Dimension d = getSize(); int w = d.width; int h = d.height; // Creates the buffered image. BufferedImage buffImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D gbi = buffImg.createGraphics(); // Clears the previously drawn image. g2.setColor(Color.white); g2.fillRect(0, 0, d.width, d.height); int rectx = w/4; int recty = h/4; // Draws the rectangle and ellipse into the buffered image. gbi.setColor(new Color(0.0f, 0.0f, 1.0f, 1.0f)); gbi.fill(new Rectangle2D.Double(rectx, recty, 150, 100)); gbi.setColor(new Color(1.0f, 0.0f, 0.0f, 1.0f)); gbi.setComposite(ac); gbi.fill(new Ellipse2D.Double(rectx+rectx/2,recty+recty/2,150,100)); // Draws the buffered image. g2.drawImage(buffImg, null, 0, 0); }

/* * @(#)ShapeMover.java */ import import import import

1.2 98/07/31

java.awt.*; java.awt.event.*; java.applet.Applet; java.awt.image.*;

/* * This applet allows the user to move a texture painted rectangle around the applet * window. The rectangle flickers and draws slowly because this applet does not use * double buffering. */ public class ShapeMover extends Applet{ static protected Label label; public void init(){ setLayout(new BorderLayout()); add(new SMCanvas()); label = new Label("Drag rectangle around within the area"); add("South", label); } public static void main(String s[]) { Frame f = new Frame("ShapeMover"); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} }); Applet applet = new ShapeMover(); f.add("Center", applet); applet.init(); f.pack(); f.setSize(new Dimension(550,250)); f.show(); } } class SMCanvas extends Canvas implements MouseListener, MouseMotionListener{ Rectangle rect = new Rectangle(0, 0, 100, 50); BufferedImage bi; Graphics2D big; // Holds the coordinates of the user's last mousePressed event. int last_x, last_y; boolean firstTime = true; TexturePaint fillPolka, strokePolka; Rectangle area; // True if the user pressed, dragged or released the mouse outside of the rectangle; false otherwise. boolean pressOut = false; public SMCanvas(){ setBackground(Color.white); addMouseMotionListener(this);

addMouseListener(this); // Creates the fill texture paint pattern. bi = new BufferedImage(5, 5, BufferedImage.TYPE_INT_RGB); big = bi.createGraphics(); big.setColor(Color.pink); big.fillRect(0, 0, 7, 7); big.setColor(Color.cyan); big.fillOval(0, 0, 3, 3); Rectangle r = new Rectangle(0,0,5,5); fillPolka = new TexturePaint(bi, r); big.dispose(); //Creates the stroke texture paint pattern. bi = new BufferedImage(5, 5, BufferedImage.TYPE_INT_RGB); big = bi.createGraphics(); big.setColor(Color.cyan); big.fillRect(0, 0, 7, 7); big.setColor(Color.pink); big.fillOval(0, 0, 3, 3); r = new Rectangle(0,0,5,5); strokePolka = new TexturePaint(bi, r); big.dispose(); } // Handles the event of the user pressing down the mouse button. public void mousePressed(MouseEvent e){ last_x = rect.x - e.getX(); last_y = rect.y - e.getY(); // Checks whether or not the cursor is inside of the rectangle while the user is pressing the mouse. if(rect.contains(e.getX(), e.getY())) updateLocation(e); else { ShapeMover.label.setText("First position the cursor on the rectangle and then drag."); pressOut = true; } } // Handles the event of a user dragging the mouse while holding down the mouse button. public void mouseDragged(MouseEvent e){ if(!pressOut) updateLocation(e); else ShapeMover.label.setText("First position the cursor on the rectangle and then drag."); } // Handles the event of a user releasing the mouse button. public void mouseReleased(MouseEvent e){ // Checks whether or not the cursor is inside of the rectangle when the user releases the mouse button. if(rect.contains(e.getX(), e.getY())) updateLocation(e); else { ShapeMover.label.setText("First position the cursor on the rectangle and then drag."); pressOut = false; } } // This method required by MouseListener. public void mouseMoved(MouseEvent e){}

// These methods are required by MouseMotionListener. public void mouseClicked(MouseEvent e){} public void mouseExited(MouseEvent e){} public void mouseEntered(MouseEvent e){} // Updates the coordinates representing the location of the current rectangle. public void updateLocation(MouseEvent e){ rect.setLocation(last_x + e.getX(), last_y + e.getY()); /* * Updates the label to reflect the location of the * current rectangle * if checkRect returns true; otherwise, returns error message. */ if (checkRect()) { ShapeMover.label.setText("Rectangle located at " + rect.getX() + ", " + rect.getY()); } else { ShapeMover.label.setText("Please don't try to "+ " drag outside the area."); } repaint(); } public void paint(Graphics g){ update(g); } public void update(Graphics g){ Graphics2D g2 = (Graphics2D)g; Dimension dim = getSize(); int w = (int)dim.getWidth(); int h = (int)dim.getHeight(); g2.setStroke(new BasicStroke(8.0f)); if(firstTime){ area = new Rectangle(dim); rect.setLocation(w/2-50, h/2-25); firstTime = false; } // Clears the rectangle that was previously drawn. g2.setPaint(Color.white); g2.fillRect(0, 0, w, h); // Draws and fills the newly positioned rectangle. g2.setPaint(strokePolka); g2.draw(rect); g2.setPaint(fillPolka); g2.fill(rect); } /* * Checks if the rectangle is contained within the applet window. If the rectangle * is not contained withing the applet window, it is redrawn so that it is adjacent * to the edge of the window and just inside the window. */ boolean checkRect(){ if (area == null) {

return false; } if(area.contains(rect.x, rect.y, 100, 50)){ return true; } int new_x = rect.x; int new_y = rect.y; if((rect.x+100)>area.getWidth()){ new_x = (int)area.getWidth()-99; } if(rect.x < 0){ new_x = -1; } if((rect.y+50)>area.getHeight()){ new_y = (int)area.getHeight()-49; } if(rect.y < 0){ new_y = -1; } rect.setLocation(new_x, new_y); return false; } }

import import import import import import import import import import import import import import import import

javax.swing.*; java.awt.*; java.awt.font.FontRenderContext; java.awt.font.TextHitInfo; java.awt.font.TextLayout; java.awt.geom.Point2D; java.awt.event.MouseAdapter; java.awt.event.MouseEvent; java.awt.event.WindowAdapter; java.awt.event.WindowEvent; java.text.AttributedCharacterIterator; java.text.AttributedCharacterIterator; java.text.AttributedString; java.awt.font.TextAttribute; java.util.Hashtable; java.util.Enumeration;

/** * This class demonstrates how to hit-test a TextLayout. Hit-testing * is the mapping of a graphical location to a character position within * text. * * This class constructs a TextLayout from an AttributedCharacterIterator * and displays the TextLayout. When the mouse is clicked inside this * Component, the mouse position is mapped to a character position, and the * carets for this character position are displayed. */ public class HitTestSample extends JApplet { // Colors to use for the strong and weak carets. private static final Color STRONG_CARET_COLOR = Color.red; private static final Color WEAK_CARET_COLOR = Color.black; // The TextLayout to draw and hit-test. private TextLayout textLayout; // The insertion index of the most recent mouse click. private int insertionIndex; private static final FontRenderContext DEFAULT_FRC = new FontRenderContext(null, false, false); private static final Hashtable map = new Hashtable(); static { map.put(TextAttribute.SIZE, new Float(18.0)); } // text to use in samples: private static AttributedString helloWorld = new AttributedString("Hello World", map); Dimension preferredSize = new Dimension(400, 250); HitPane hitPane; public void init() { AttributedCharacterIterator text = helloWorld.getIterator(); buildUI(getContentPane(), text); } public void buildUI(Container container, AttributedCharacterIterator text){

// Create a new TextLayout from the given text. textLayout = new TextLayout(text, DEFAULT_FRC); // Initilize insertionIndex. insertionIndex = 0; hitPane = new HitPane(); container.add(hitPane, BorderLayout.CENTER); hitPane.addMouseListener(new HitTestMouseListener()); } public Dimension getPreferredSize() { return preferredSize; } /** * Compute a location within this Component for textLayout's origin, * such that textLayout is centered horizontally and vertically. * * Note that this location is unknown to textLayout; it is used only * by this Component for positioning. */ private Point2D computeLayoutOrigin() { Dimension size = getPreferredSize(); Point2D.Float origin = new Point2D.Float(); origin.x = (float) (size.width - textLayout.getAdvance()) / 2; origin.y = (float) (size.height - textLayout.getDescent() + textLayout.getAscent()) / 2; return origin; } class HitPane extends JPanel { public void HitPane() {} /** * Draw textLayout and the carets corresponding to the most recent * mouse click (if any). */ public void paintComponent(Graphics g) { super.paintComponent(g); setBackground(Color.white); Graphics2D graphics2D = (Graphics2D) g; Point2D origin = computeLayoutOrigin(); // // // // Since the caret Shapes are relative to the origin of textLayout, we'll translate the graphics so that the origin of the graphics is where we want textLayout to appear.

graphics2D.translate(origin.getX(), origin.getY()); // Draw textLayout. textLayout.draw(graphics2D, 0, 0); // Retrieve caret Shapes for insertionIndex. Shape[] carets = textLayout.getCaretShapes(insertionIndex); // Draw the carets. carets[0] is the strong caret, and // is never null. carets[1], if it is not null, is the

// weak caret. graphics2D.setColor(STRONG_CARET_COLOR); graphics2D.draw(carets[0]); if (carets[1] != null) { graphics2D.setColor(WEAK_CARET_COLOR); graphics2D.draw(carets[1]); } } } private class HitTestMouseListener extends MouseAdapter { /** * Compute the character position of the mouse click. */ public void mouseClicked(MouseEvent e) { Point2D origin = computeLayoutOrigin(); // Compute the mouse click location relative to // textLayout's origin. float clickX = (float) (e.getX() - origin.getX()); float clickY = (float) (e.getY() - origin.getY()); // Get the character position of the mouse click. TextHitInfo currentHit = textLayout.hitTestChar(clickX, clickY); insertionIndex = currentHit.getInsertionIndex(); // Repaint the Component so the new caret(s) will be displayed. hitPane.repaint(); } } public static void main(String[] args) { JFrame sampleFrame = new JFrame("HitTestSample"); AttributedCharacterIterator text = helloWorld.getIterator(); final HitTestSample controller = new HitTestSample(); controller.buildUI(sampleFrame.getContentPane(), text); sampleFrame.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e) { System.exit(0); } }); sampleFrame.setSize(new Dimension(400, 250)); sampleFrame.setVisible(true); } }

/* * @(#)FontSelection.java */ import import import import import import import java.lang.Integer; java.awt.*; java.awt.font.*; java.awt.geom.*; java.awt.event.*; javax.swing.*; java.util.Vector;

1.2 98/07/31

/* * This applet displays a String with the user's selected * fontname, style and size attributes. */ public class FontSelection extends JApplet implements ItemListener { JLabel fontLabel, sizeLabel, styleLabel; FontPanel fontC; JComboBox fonts, sizes, styles; int index = 0; String fontchoice = "fontchoice"; int stChoice = 0; String siChoice = "10"; public void init() { getContentPane().setLayout( new BorderLayout() ); JPanel JPanel JPanel JPanel JPanel topPanel = new JPanel(); fontPanel = new JPanel(); sizePanel = new JPanel(); stylePanel = new JPanel(); sizeAndStylePanel = new JPanel();

topPanel.setLayout( new BorderLayout() ); fontPanel.setLayout( new GridLayout( 2, 1 ) ); sizePanel.setLayout( new GridLayout( 2, 1 ) ); stylePanel.setLayout( new GridLayout( 2, 1 ) ); sizeAndStylePanel.setLayout( new BorderLayout() ); topPanel.add( BorderLayout.WEST, fontPanel ); sizeAndStylePanel.add( BorderLayout.WEST, sizePanel ); sizeAndStylePanel.add( BorderLayout.CENTER, stylePanel ); topPanel.add( BorderLayout.CENTER, sizeAndStylePanel ); getContentPane().add( BorderLayout.NORTH, topPanel ); fontLabel = new JLabel(); fontLabel.setText("Fonts"); Font newFont = getFont().deriveFont(1); fontLabel.setFont(newFont); fontLabel.setHorizontalAlignment(JLabel.CENTER); fontPanel.add(fontLabel); sizeLabel = new JLabel(); sizeLabel.setText("Sizes"); sizeLabel.setFont(newFont); sizeLabel.setHorizontalAlignment(JLabel.CENTER); sizePanel.add(sizeLabel); styleLabel = new JLabel();

styleLabel.setText("Styles"); styleLabel.setFont(newFont); styleLabel.setHorizontalAlignment(JLabel.CENTER); stylePanel.add(styleLabel); GraphicsEnvironment gEnv = GraphicsEnvironment.getLocalGraphicsEnvironment(); String envfonts[] = gEnv.getAvailableFontFamilyNames(); Vector vector = new Vector(); for ( int i = 1; i < envfonts.length; i++ ) { vector.addElement(envfonts[i]); } fonts = new JComboBox( vector ); fonts.setMaximumRowCount( 9 ); fonts.addItemListener(this); fontchoice = envfonts[0]; fontPanel.add(fonts); sizes = new JComboBox( new Object[]{ "10", "12", "14", "16", "18"} ); sizes.setMaximumRowCount( 9 ); sizes.addItemListener(this); sizePanel.add(sizes); styles = new JComboBox( new Object[]{ "PLAIN", "BOLD", "ITALIC", "BOLD & ITALIC"} ); styles.setMaximumRowCount( 9 ); styles.addItemListener(this); sizes.setMaximumRowCount( 9 ); stylePanel.add(styles); fontC = new FontPanel(); fontC.setBackground(Color.white); getContentPane().add( BorderLayout.CENTER, fontC); } /* * Detects a state change in any of the Lists. Resets the variable corresponding * to the selected item in a particular List. Invokes changeFont with the currently * selected fontname, style and size attributes. */ public void itemStateChanged(ItemEvent e) { if ( e.getStateChange() != ItemEvent.SELECTED ) { return; } Object list = e.getSource(); if ( list == fonts ) { fontchoice = (String)fonts.getSelectedItem(); } else if ( list == styles ) { index = styles.getSelectedIndex(); stChoice = index; } else { siChoice = (String)sizes.getSelectedItem(); } fontC.changeFont(fontchoice, stChoice, siChoice); } public static void main(String s[]) { JFrame f = new JFrame("FontSelection");

f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} }); JApplet fontSelection = new FontSelection(); f.getContentPane().add(fontSelection, BorderLayout.CENTER); fontSelection.init(); f.setSize(new Dimension(550,250)); f.setVisible(true); } } class FontPanel extends JPanel { Font thisFont; public FontPanel(){ thisFont = new Font("Arial", Font.PLAIN, 10); } // Resets thisFont to the currently selected fontname, size and style attributes. public void changeFont(String f, int st, String si){ Integer newSize = new Integer(si); int size = newSize.intValue(); thisFont = new Font(f, st, size); repaint(); } public void paintComponent (Graphics g) { super.paintComponent( g ); Graphics2D g2 = (Graphics2D) g; int w = getWidth(); int h = getHeight(); g2.setColor(Color.darkGray); g2.setFont(thisFont); String change = "Pick a font, size, and style to change me"; FontMetrics metrics = g2.getFontMetrics(); int width = metrics.stringWidth( change ); int height = metrics.getHeight(); g2.drawString( change, w/2-width/2, h/2-height/2 ); } }

import import import import import import import import import import import

javax.swing.*; java.awt.*; java.awt.font.FontRenderContext; java.awt.font.LineBreakMeasurer; java.awt.font.TextLayout; java.util.Hashtable; java.text.AttributedCharacterIterator; java.text.AttributedString; java.awt.font.TextAttribute; java.awt.event.WindowAdapter; java.awt.event.WindowEvent;

/** * This class demonstrates how to line-break and draw a paragraph * of text using LineBreakMeasurer and TextLayout. * * This class constructs a LineBreakMeasurer from an * AttributedCharacterIterator. It uses the LineBreakMeasurer * to create and draw TextLayouts (lines of text) which fit within * the Component's width. */ public class LineBreakSample extends JApplet { // The LineBreakMeasurer used to line-break the paragraph. private LineBreakMeasurer lineMeasurer; // The index in the LineBreakMeasurer of the first character // in the paragraph. private int paragraphStart; // The index in the LineBreakMeasurer of the first character // after the end of the paragraph. private int paragraphEnd; private static final Hashtable map = new Hashtable(); static { map.put(TextAttribute.SIZE, new Float(18.0)); } private static AttributedString vanGogh = new AttributedString( "Many people believe that Vincent van Gogh painted his best works " + "during the two-year period he spent in Provence. Here is where he " + "painted The Starry Night--which some consider to be his greatest " + "work of all. However, as his artistic brilliance reached new heights " + "in Provence, his physical and mental health plummeted. ", map); public void init() { buildUI(getContentPane()); } public void buildUI(Container container){ LineBreakPanel lineBreakPanel = new LineBreakPanel(); container.add(lineBreakPanel, BorderLayout.CENTER); } class LineBreakPanel extends JPanel { public LineBreakPanel() { AttributedCharacterIterator paragraph = vanGogh.getIterator(); paragraphStart = paragraph.getBeginIndex(); paragraphEnd = paragraph.getEndIndex(); // Create a new LineBreakMeasurer from the paragraph.

lineMeasurer = new LineBreakMeasurer(paragraph, new FontRenderContext(null, false, false)); } public void paintComponent(Graphics g) { super.paintComponent(g); setBackground(Color.white); Graphics2D graphics2D = (Graphics2D) g; // Set formatting width to width of Component. Dimension size = getSize(); float formatWidth = (float) size.width; float drawPosY = 0; lineMeasurer.setPosition(paragraphStart); // Get lines from lineMeasurer until the entire // paragraph has been displayed. while (lineMeasurer.getPosition() < paragraphEnd) { // Retrieve next layout. TextLayout layout = lineMeasurer.nextLayout(formatWidth); // Move y-coordinate by the ascent of the layout. drawPosY += layout.getAscent(); // Compute pen x position. If the paragraph is // right-to-left, we want to align the TextLayouts // to the right edge of the panel. float drawPosX; if (layout.isLeftToRight()) { drawPosX = 0; } else { drawPosX = formatWidth - layout.getAdvance(); } // Draw the TextLayout at (drawPosX, drawPosY). layout.draw(graphics2D, drawPosX, drawPosY); // Move y-coordinate in preparation for next layout. drawPosY += layout.getDescent() + layout.getLeading(); } } } public static void main(String[] args) { JFrame f = new JFrame("HitTestSample"); f.addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e) { System.exit(0); } }); LineBreakSample controller = new LineBreakSample(); controller.buildUI(f.getContentPane()); f.setSize(new Dimension(400, 250)); f.setVisible(true); }

/* * @(#)ImageOps.java */ import import import import import import import import import

1.2 98/07/09

java.awt.*; java.awt.event.*; javax.swing.*; java.awt.image.*; java.awt.geom.AffineTransform; java.awt.font.TextLayout; java.awt.event.WindowEvent; java.awt.event.WindowListener; java.awt.event.WindowAdapter;

import java.net.URL; public class ImageOps extends JApplet { private BufferedImage bi[]; public static final float[] SHARPEN3x3_3 = { 0.f, -1.f, 0.f, -1.f, 5.f, -1.f, 0.f, -1.f, 0.f}; public void init() { setBackground(Color.white); bi = new BufferedImage[4]; String s[] = { "bld.jpg", "bld.jpg", "boat.gif", "boat.gif"}; for ( int i = 0; i < bi.length; i++ ) { Image img = getImage(getURL("images/" + s[i])); try { MediaTracker tracker = new MediaTracker(this); tracker.addImage(img, 0); tracker.waitForID(0); } catch ( Exception e ) {} int iw = img.getWidth(this); int ih = img.getHeight(this); bi[i] = new BufferedImage(iw, ih, BufferedImage.TYPE_INT_RGB); Graphics2D big = bi[i].createGraphics(); big.drawImage(img,0,0,this); } } public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); int w = getSize().width; int h = getSize().height; g2.setColor(Color.black); float[][] data = {{0.1f, 0.1f, 0.1f, 0.1f, 0.2f, 0.1f, 0.1f, 0.1f, 0.1f}, SHARPEN3x3_3}; // low-pass filter

String theDesc[] = { "Convolve LowPass", "Convolve Sharpen", "LookupOp", "RescaleOp"}; for ( int i = 0; i < bi.length; i++ ) {

int iw = bi[i].getWidth(this); int ih = bi[i].getHeight(this); int x = 0, y = 0; AffineTransform at = new AffineTransform(); at.scale((w-14)/2.0/iw, (h-34)/2.0/ih); BufferedImageOp biop = null; BufferedImage bimg = new BufferedImage(iw,ih,BufferedImage.TYPE_INT_RGB); switch ( i ) { case 0 : case 1 : x = i==0?5:w/2+3; y = 15; Kernel kernel = new Kernel(3,3,data[i]); ConvolveOp cop = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null); cop.filter(bi[i],bimg); biop = new AffineTransformOp(at, AffineTransformOp.TYPE_NEAREST_NEIGHBOR); break; case 2 : x = 5; y = h/2+15; byte chlut[] = new byte[256]; for ( int j=0;j<200 ;j++ ) chlut[j]=(byte)(256-j); ByteLookupTable blut=new ByteLookupTable(0,chlut); LookupOp lop = new LookupOp(blut, null); lop.filter(bi[i],bimg); biop = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR); break; case 3 : x = w/2+3; y = h/2+15; RescaleOp rop = new RescaleOp(1.1f,20.0f, null); rop.filter(bi[i],bimg); biop = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR); } g2.drawImage(bimg,biop,x,y); TextLayout tl = new TextLayout(theDesc[i], g2.getFont(),g2.getFontRenderContext()); tl.draw(g2, (float) x, (float) y-4); } } protected URL getURL(String filename) { URL codeBase = this.getCodeBase(); URL url = null; try { url = new URL(codeBase, filename); } catch (java.net.MalformedURLException e) { System.out.println("Couldn't create image: " + "badly specified URL"); return null; } return url; } public static void main(String s[]) { JFrame f = new JFrame("ImageOps"); f.addWindowListener(new WindowAdapter() {

public void windowClosing(WindowEvent e) {System.exit(0);} }); JApplet applet = new ImageOps(); f.getContentPane().add("Center", applet); applet.init(); f.pack(); f.setSize(new Dimension(550,550)); f.show(); } }

import import import import

java.awt.*; java.awt.event.*; java.applet.Applet; java.awt.image.*;

public class BufferedShapeMover extends Applet{ static protected Label label; public void init(){ //Initialize the layout. setLayout(new BorderLayout()); add(new BSMCanvas()); label = new Label("Drag rectangle around within the area"); add("South", label); } public static void main(String s[]) { Frame f = new Frame("BufferedShapeMover"); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} }); Applet applet = new BufferedShapeMover(); f.add("Center", applet); applet.init(); f.pack(); f.setSize(new Dimension(550,250)); f.show(); } } class BSMCanvas extends Canvas implements MouseListener, MouseMotionListener{ Rectangle rect = new Rectangle(0, 0, 100, 50); BufferedImage bi; Graphics2D big; // Holds the coordinates of the user's last mousePressed event. int last_x, last_y; boolean firstTime = true; TexturePaint fillPolka, strokePolka; Rectangle area; // True if the user pressed, dragged or released the mouse outside of the rectangle; false otherwise. boolean pressOut = false; public BSMCanvas(){ setBackground(Color.white); addMouseMotionListener(this); addMouseListener(this); // Creates the fill texture paint pattern. bi = new BufferedImage(5, 5, BufferedImage.TYPE_INT_RGB); big = bi.createGraphics(); big.setColor(Color.pink); big.fillRect(0, 0, 7, 7); big.setColor(Color.cyan); big.fillOval(0, 0, 3, 3); Rectangle r = new Rectangle(0,0,5,5); fillPolka = new TexturePaint(bi, r); big.dispose();

//Creates the stroke texture paint pattern. bi = new BufferedImage(5, 5, BufferedImage.TYPE_INT_RGB); big = bi.createGraphics(); big.setColor(Color.cyan); big.fillRect(0, 0, 7, 7); big.setColor(Color.pink); big.fillOval(0, 0, 3, 3); r = new Rectangle(0,0,5,5); strokePolka = new TexturePaint(bi, r); big.dispose(); } // Handles the event of the user pressing down the mouse button. public void mousePressed(MouseEvent e){ last_x = rect.x - e.getX(); last_y = rect.y - e.getY(); // Checks whether or not the cursor is inside of the rectangle while the user is pressing themouse. if(rect.contains(e.getX(), e.getY())){ updateLocation(e); } else { BufferedShapeMover.label.setText("First position the cursor on the rectangle and then drag."); pressOut = true; } } // Handles the event of a user dragging the mouse while holding down the mouse button. public void mouseDragged(MouseEvent e){ if(!pressOut){ updateLocation(e); } else { BufferedShapeMover.label.setText("First position the cursor on the rectangle and then drag."); } } // Handles the event of a user releasing the mouse button. public void mouseReleased(MouseEvent e){ // Checks whether or not the cursor is inside of the rectangle when the user releases the // mouse button. if(rect.contains(e.getX(), e.getY())){ updateLocation(e); } else { BufferedShapeMover.label.setText("First position the cursor on the rectangle and then drag."); pressOut = false; } } // This method required by MouseListener. public void mouseMoved(MouseEvent e){} // These methods are required by MouseMotionListener. public void mouseClicked(MouseEvent e){} public void mouseExited(MouseEvent e){} public void mouseEntered(MouseEvent e){} public void updateLocation(MouseEvent e){

rect.setLocation(last_x + e.getX(), last_y + e.getY()); /* * Updates the label to reflect the location of the * current rectangle * if checkRect returns true; otherwise, returns error message. */ if (checkRect()) { BufferedShapeMover.label.setText("Rectangle located at " + rect.getX() + ", " + rect.getY()); } else { BufferedShapeMover.label.setText("Please don't try to "+ " drag outside the area."); } repaint(); } public void paint(Graphics g){ update(g); } public void update(Graphics g){ Graphics2D g2 = (Graphics2D)g; if(firstTime){ Dimension dim = getSize(); int w = dim.width; int h = dim.height; area = new Rectangle(dim); bi = (BufferedImage)createImage(w, h); big = bi.createGraphics(); rect.setLocation(w/2-50, h/2-25); big.setStroke(new BasicStroke(8.0f)); firstTime = false; } // Clears the rectangle that was previously drawn. big.setColor(Color.white); big.clearRect(0, 0, area.width, area.height); // Draws and fills the newly positioned rectangle to the buffer. big.setPaint(strokePolka); big.draw(rect); big.setPaint(fillPolka); big.fill(rect); // Draws the buffered image to the screen. g2.drawImage(bi, 0, 0, this); } /* * Checks if the rectangle is contained within the applet window. If the rectangle * is not contained withing the applet window, it is redrawn so that it is adjacent * to the edge of the window and just inside the window. */ boolean checkRect(){ if (area == null) { return false; } if(area.contains(rect.x, rect.y, 100, 50)){ return true; }

int new_x = rect.x; int new_y = rect.y; if((rect.x+100)>area.width){ new_x = area.width-99; } if(rect.x < 0){ new_x = -1; } if((rect.y+50)>area.height){ new_y = area.height-49; } if(rect.y < 0){ new_y = -1; } rect.setLocation(new_x, new_y); return false; } }

import import import import import import import import

java.awt.geom.*; java.awt.event.ActionListener; java.awt.event.ActionEvent; java.awt.print.PrinterJob; java.awt.event.*; java.awt.*; javax.swing.*; java.awt.print.*;

public class ShapesPrint extends JPanel implements Printable, ActionListener { final final final final static static static static Color Color Color Color bg = Color.white; fg = Color.black; red = Color.red; white = Color.white;

final static BasicStroke stroke = new BasicStroke(2.0f); final static BasicStroke wideStroke = new BasicStroke(8.0f); final static float dash1[] = {10.0f}; final static BasicStroke dashed = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, dash1, 0.0f); final static JButton button = new JButton("Print"); public ShapesPrint() { setBackground(bg); button.addActionListener(this); } public void actionPerformed(ActionEvent e) { if (e.getSource() instanceof JButton) { PrinterJob printJob = PrinterJob.getPrinterJob(); printJob.setPrintable(this); if (printJob.printDialog()) { try { printJob.print(); } catch (Exception ex) { ex.printStackTrace(); } } } } public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; drawShapes(g2); } public void drawShapes(Graphics2D g2){ Dimension d = getSize(); int gridWidth = 400 / 6; int gridHeight = 300 / 2; int int int int rowspacing = 5; columnspacing = 7; rectWidth = gridWidth - columnspacing; rectHeight = gridHeight - rowspacing;

Color fg3D = Color.lightGray; g2.setPaint(fg3D);

g2.drawRect(80, 80, 400 - 1, 310); g2.setPaint(fg); int x = 85; int y = 87; // draw Line2D.Double g2.draw(new Line2D.Double(x, y+rectHeight-1, x + rectWidth, y)); x += gridWidth; // draw Rectangle2D.Double g2.setStroke(stroke); g2.draw(new Rectangle2D.Double(x, y, rectWidth, rectHeight)); x += gridWidth; // draw RoundRectangle2D.Double g2.setStroke(dashed); g2.draw(new RoundRectangle2D.Double(x, y, rectWidth, rectHeight, 10, 10)); x += gridWidth; // draw Arc2D.Double g2.setStroke(wideStroke); g2.draw(new Arc2D.Double(x, y, rectWidth, rectHeight, 90, 135, Arc2D.OPEN)); x += gridWidth; // draw Ellipse2D.Double g2.setStroke(stroke); g2.draw(new Ellipse2D.Double(x, y, rectWidth, rectHeight)); x += gridWidth; // draw GeneralPath (polygon) int x1Points[] = {x, x+rectWidth, x, x+rectWidth}; int y1Points[] = {y, y+rectHeight, y+rectHeight, y}; GeneralPath polygon = new GeneralPath(GeneralPath.WIND_EVEN_ODD, x1Points.length); polygon.moveTo(x1Points[0], y1Points[0]); for ( int index = 1; index < x1Points.length; index++ ) { polygon.lineTo(x1Points[index], y1Points[index]); }; polygon.closePath(); g2.draw(polygon); // NEW ROW x = 85; y += gridHeight; // draw GeneralPath (polyline) int x2Points[] = {x, x+rectWidth, x, x+rectWidth}; int y2Points[] = {y, y+rectHeight, y+rectHeight, y}; GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, x2Points.length); polyline.moveTo (x2Points[0], y2Points[0]); for ( int index = 1; index < x2Points.length; index++ ) { polyline.lineTo(x2Points[index], y2Points[index]); }; g2.draw(polyline); x += gridWidth;

// fill Rectangle2D.Double (red) g2.setPaint(red); g2.fill(new Rectangle2D.Double(x, y, rectWidth, rectHeight)); g2.setPaint(fg); x += gridWidth; // fill RoundRectangle2D.Double GradientPaint redtowhite = new GradientPaint(x,y,red,x+rectWidth, y,white); g2.setPaint(redtowhite); g2.fill(new RoundRectangle2D.Double(x, y, rectWidth, rectHeight, 10, 10)); g2.setPaint(fg); x += gridWidth; // fill Arc2D g2.setPaint(red); g2.fill(new Arc2D.Double(x, y, rectWidth, rectHeight, 90, 135, Arc2D.OPEN)); g2.setPaint(fg); x += gridWidth; // fill Ellipse2D.Double redtowhite = new GradientPaint(x,y,red,x+rectWidth, y,white); g2.setPaint(redtowhite); g2.fill (new Ellipse2D.Double(x, y, rectWidth, rectHeight)); g2.setPaint(fg); x += gridWidth; // fill and stroke GeneralPath int x3Points[] = {x, x+rectWidth, x, x+rectWidth}; int y3Points[] = {y, y+rectHeight, y+rectHeight, y}; GeneralPath filledPolygon = new GeneralPath(GeneralPath.WIND_EVEN_ODD, x3Points.length); filledPolygon.moveTo(x3Points[0], y3Points[0]); for ( int index = 1; index < x3Points.length; index++ ) { filledPolygon.lineTo(x3Points[index], y3Points[index]); }; filledPolygon.closePath(); g2.setPaint(red); g2.fill(filledPolygon); g2.setPaint(fg); g2.draw(filledPolygon); } public int print(Graphics g, PageFormat pf, int pi) throws PrinterException { if (pi >= 1) { return Printable.NO_SUCH_PAGE; } drawShapes((Graphics2D) g); return Printable.PAGE_EXISTS; } public static void main(String s[]){ WindowListener l = new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} public void windowClosed(WindowEvent e) {System.exit(0);} }; JFrame f = new JFrame(); f.addWindowListener(l); JPanel panel = new JPanel(); panel.add(button); f.getContentPane().add(BorderLayout.SOUTH, panel); f.getContentPane().add(BorderLayout.CENTER, new ShapesPrint());

f.setSize(580, 500); f.show(); } }

import import import import import import import

java.awt.event.*; javax.swing.*; java.awt.event.ActionListener; java.awt.event.ActionEvent; java.awt.*; java.awt.geom.*; java.awt.print.*;

public class SimpleBook extends JPanel implements ActionListener{ final static Color bg = Color.white; final static Color fg = Color.black; final static Color red = Color.red; final static Color white = Color.white; final static BasicStroke stroke = new BasicStroke(2.0f); final static BasicStroke wideStroke = new BasicStroke(8.0f); final static float dash1[] = {10.0f}; final static BasicStroke dashed = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, dash1, 0.0f); final static JButton button = new JButton("Print"); public SimpleBook() { setBackground(bg); button.addActionListener(this); } public void actionPerformed(ActionEvent e) { // Get a PrinterJob PrinterJob job = PrinterJob.getPrinterJob(); // Create a landscape page format PageFormat landscape = job.defaultPage(); landscape.setOrientation(PageFormat.LANDSCAPE); // Set up a book Book bk = new Book(); bk.append(new PaintCover(), job.defaultPage()); bk.append(new PaintContent(), landscape); // Pass the book to the PrinterJob job.setPageable(bk); // Put up the dialog box if (job.printDialog()) { // Print the job if the user didn't cancel printing try { job.print(); } catch (Exception exc) { /* Handle Exception */ } } } public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; drawShapes(g2); } static void drawShapes(Graphics2D g2){ int gridWidth = 600 / 6; int gridHeight = 250 / 2; int rowspacing = 5; int columnspacing = 7; int rectWidth = gridWidth - columnspacing;

int rectHeight = gridHeight - rowspacing; Color fg3D = Color.lightGray; g2.setPaint(fg3D); g2.drawRect(80, 80, 605 - 1, 265); g2.setPaint(fg); int x = 85; int y = 87; // draw Line2D.Double g2.draw(new Line2D.Double(x, y+rectHeight-1, x + rectWidth, y)); x += gridWidth; Graphics2D temp = g2; // draw Rectangle2D.Double g2.setStroke(stroke); g2.draw(new Rectangle2D.Double(x, y, rectWidth, rectHeight)); x += gridWidth; // draw RoundRectangle2D.Double g2.setStroke(dashed); g2.draw(new RoundRectangle2D.Double(x, y, rectWidth, rectHeight, 10, 10)); x += gridWidth; // draw Arc2D.Double g2.setStroke(wideStroke); g2.draw(new Arc2D.Double(x, y, rectWidth, rectHeight, 90, 135, Arc2D.OPEN)); x += gridWidth; // draw Ellipse2D.Double g2.setStroke(stroke); g2.draw(new Ellipse2D.Double(x, y, rectWidth, rectHeight)); x += gridWidth; // draw GeneralPath (polygon) int x1Points[] = {x, x+rectWidth, x, x+rectWidth}; int y1Points[] = {y, y+rectHeight, y+rectHeight, y}; GeneralPath polygon = new GeneralPath(GeneralPath.WIND_EVEN_ODD, x1Points.length); polygon.moveTo(x1Points[0], y1Points[0]); for ( int index = 1; index < x1Points.length; index++ ) { polygon.lineTo(x1Points[index], y1Points[index]); }; polygon.closePath(); g2.draw(polygon); // NEW ROW x = 85; y += gridHeight; // draw GeneralPath (polyline) int x2Points[] = {x, x+rectWidth, x, x+rectWidth}; int y2Points[] = {y, y+rectHeight, y+rectHeight, y}; GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, x2Points.length); polyline.moveTo (x2Points[0], y2Points[0]);

for ( int index = 1; index < x2Points.length; index++ ) { polyline.lineTo(x2Points[index], y2Points[index]); }; g2.draw(polyline); x += gridWidth; // fill Rectangle2D.Double (red) g2.setPaint(red); g2.fill(new Rectangle2D.Double(x, y, rectWidth, rectHeight)); g2.setPaint(fg); x += gridWidth; // fill RoundRectangle2D.Double GradientPaint redtowhite = new GradientPaint(x,y,red,x+rectWidth,y,white); g2.setPaint(redtowhite); g2.fill(new RoundRectangle2D.Double(x, y, rectWidth, rectHeight, 10, 10)); g2.setPaint(fg); x += gridWidth; // fill Arc2D g2.setPaint(red); g2.fill(new Arc2D.Double(x, y, rectWidth, rectHeight, 90, 135, Arc2D.OPEN)); g2.setPaint(fg); x += gridWidth; // fill Ellipse2D.Double redtowhite = new GradientPaint(x,y,red,x+rectWidth, y,white); g2.setPaint(redtowhite); g2.fill (new Ellipse2D.Double(x, y, rectWidth, rectHeight)); g2.setPaint(fg); x += gridWidth; // fill and stroke GeneralPath int x3Points[] = {x, x+rectWidth, x, x+rectWidth}; int y3Points[] = {y, y+rectHeight, y+rectHeight, y}; GeneralPath filledPolygon = new GeneralPath(GeneralPath.WIND_EVEN_ODD, x3Points.length); filledPolygon.moveTo(x3Points[0], y3Points[0]); for ( int index = 1; index < x3Points.length; index++ ) { filledPolygon.lineTo(x3Points[index], y3Points[index]); }; filledPolygon.closePath(); g2.setPaint(red); g2.fill(filledPolygon); g2.setPaint(fg); g2.draw(filledPolygon); g2.setStroke(temp.getStroke()); }

public static void main(String[] args) { WindowListener l = new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} public void windowClosed(WindowEvent e) {System.exit(0);} }; JFrame f = new JFrame(); f.addWindowListener(l); JPanel panel = new JPanel(); panel.add(button); f.getContentPane().add(BorderLayout.SOUTH, panel); f.getContentPane().add(BorderLayout.CENTER, new SimpleBook());

f.setSize(775, 450); f.show(); } } class PaintCover implements Printable { Font fnt = new Font("Helvetica-Bold", Font.PLAIN, 48); public int print(Graphics g, PageFormat pf, int pageIndex) throws PrinterException { g.setFont(fnt); g.setColor(Color.black); g.drawString("Sample Shapes", 100, 200); return Printable.PAGE_EXISTS; } } class PaintContent implements Printable { public int print(Graphics g, PageFormat pf, int pageIndex) throws PrinterException { SimpleBook.drawShapes((Graphics2D) g); return Printable.PAGE_EXISTS; } }

También podría gustarte