Graficos 2D
Graficos 2D
Graficos 2D
Indice de contenidos
● Gráficos en 2 Dimensiones
● Sistema de Coordenadas
● Formas 2D
❍ Formas Rectangulares
❍ QuadCurve2D y CubicCurve2D
❍ GeneralPath
❍ Areas
● Texto en Java 2D
❍ Fuentes
❍ Distribución de Texto
● Imágenes
● Impresión
● Mostrar Gráficos con Graphics2D
● Punteado y Relleno de Gráficos Primitivos
❍ Dibujar Curvas
❍ Ejemplo: Quad
❍ Ejemplo: Cubic
❍ Ejemplo: Odd_Shape
❍ Estilos de Línea
❍ Patrón de Relleno
❍ Ejemplo: StrokeAndFill
● Componer Gráficos
❍ Ejemplo: Composite
● Controlar la Calidad del Dibujo
● Construir Formas Complejas desde Geométricos Primitivos
❍ Ejemplo: Areas
● Soportar Interacción con el Usuario
❍ Ejemplo: ShapeMover
❍ Ejemplo: HitTestSample
❍ Printable Jobs
❍ Pageable Jobs
En esta página:
● Gráficos en 2 Dimensiones
Gráficos en 2 Dimensiones
Esta sección nos presenta el API 2D de Java y no enseña como mostrar e imprimir gráficos en 2
dimensiones en nuestros programas Java. El API 2D de Java nos permite fácilmente:
● Dibujar líneas de cualquier anchura
● Rellenar formas con gradientes y texturas
● Mover, rotar, escalar y recortar texto y gráficos.
● Componer texto y gráficos solapados.
Por ejemplo, podríamos usar el API 2D de Java para mostrar gráficos y charts complejos que usan
varios estilos de línea y de relleno para distinguir conjuntos de datos, como se muestra en la
siguiente figura:
El API 2D de Java también nos permite almacenar datos de imágenes--por ejemplo, podemos
realizar fácilmente filtros de imágenes, como blur o recortado, como se muestra en la siguiente
figura:
Esta ruta cubre los usos más frecuentes del API 2D de Java y describe brevemente algunas de las
características más avanzadas. Para más información sobre el uso del API 2D de Java, puedes ver
Java 2D Programmer's Guide.
Introducción al API 2D de Java presenta los conceptos claves del 2D y describe su modelo de
dibujado.
Mostrar Gráficos con Graphics2D nos enseña como configurar el contexto de dibujado Graphics2D
para usar estilos de punteado y relleno divertidos, realizar transformaciones, recortar la región de
dibujo, componer gráficos 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 están disponibles en nuestro sistema y la posición del texto dentro de
un componente.
Manipular y Mostrar Imágenes esta lección explica como implementar doble buffer y cómo realizar
operaciones de filtrado de imágenes con objetos BufferedImage.
Imprimir nos enseña como renderizar gráficos 2D en una impresora y cómo imprimir documentos
complejos.
Resolver Problemas más Comunes con los Gráficos 2D ofrece las soluciones a algunos de los
problemas que nos podríamos encontrar al escribir applets y aplicaciones 2D.
TutorJava recomienda...
En esta página:
● Introducción al API 2D de Java
En esta página:
● Renderizado en Java 2D
❍ Contexto de Renderizado de Graphics2D
❍ Métodos de renderizado de Graphics2D
Renderizado en Java 2D
El mecanismo de renderizado básico es el mismo que en las versiones anteriores del JDK -- el
sistema de dibujo controla cuándo y cómo dibuja un programa. Cuando un componente necesita ser
mostrado, se llama automáticamente a su método paint o update dentro del contexto Graphics
apropiado.
El estilo de lápiz que se aplica al exterior de una forma. Este atributo stroke nos
permite dibujar líneas con cualquier tamaño de punto y patrón de sombreado y
aplicar finalizadores y decoraciones a la línea.
El estilo de relleno que se aplica al interior de la forma. Este atributo paint nos
permite rellenar formas con cólores sólidos, gradientes o patrones.
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.
Para configurar un atributo en el contexto de renderizado de Graphics2D, se usan los métodos set
Attribute.
● 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, deberíamos 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 método set para
notificarlo al contexto. La modificación de un atributo de un objeto durante el renderizado puede
causar comportamientos impredecibles.
En esta página:
● Sistema de Coordenadas
Sistema de Coordenadas
El sistema 2D de Java mantiene dos espacios de coordenadas:
● El espacio de usuario es el espacio en que se especifican los gráficos 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 lógicas independiente del dispositivo: el espacio
de coordenas que usan nuestros programas. Todos los geométricos pasados a las rutinas Java 2D
de renderizado se especifican en coordenadas de espacio de usuario.
En esta página:
● Formas 2D
❍ Formas Rectangulares
❍ QuadCurve2D y CubicCurve2D
❍ GeneralPath
❍ Areas
Formas 2D
Las clases del paquete java.awt.geom definen gráficos primitivos comunes, como puntos, líneas,
curvas, arcos, rectángulos y elipses.
Clases en el paquete java.awt.geom
Arc2D Ellipse2D QuadCurve2D
Area GeneralPath Rectangle2D
CubicCurve2D Line2D RectangularShape
Dimension2D Point2D RoundRectangle2D
Excepto para Point2D y Dimension2D, cada una de las otras clases geométricas implementa el
interface Shape, que proporciona un conjunto de métodos comunes para describir e inspeccionar
objetos geométricos bi-dimensionales.
Con estas clases podemos crear de forma virtual cualquiere forma geométrica y dibujarla a través
de Graphics2D llamando al método draw o al método fill. Por ejemplo, las formas geométricas del
siguiente applet están definidas usando los geométricos básicos de Java 2D.
Formas Rectangulares
Los primitivos Rectangle2D, RoundRectangle2D, Arc2D, y Ellipse2D descienden del
RectangularShape, que define métodos para objetos Shape que pueden ser descritos por una
caja rectángular. La geometría de un RectangularShape puede ser extrapolada desde un
rectángulo que encierra completamente el exterior de la Shape.
QuadCurve2D y CubicCurve2D
La clase QuadCurve2D nos permite crear segmentos de curvas cuadráticos. Una curva cuadrática
está definida por dos puntos finales y un punto de control.
La clase CubicCurve2D nos permite crear segmentos de curvas cúbicos. Una curva cúbica está
definida por dos puntos finales y dos puntos de control. Las siguientes figuras muestran ejemplos de
curvas cuadráticas y cúbicas.
GeneralPath
La clase GeneralPath nos permite crear una curva arbitraria especificando una serie de posiciones
a lo largo de los límites de la forma. Estas posiciones pueden ser conectadas por segmentos de
línea, curvas cuadráticas o curvas cúbicas. La siguiente figura puede ser creada con 3 segmentos de
línea y una curva cúbica.
Areas
Con la clase Area podemos realizar operaciones boolenas, como uniones, intersecciones y
substracciones, sobre dos objetos Shape cualesquiera. Esta técnica, nos permite crear rápidamente
objetos Shape complejos sin tener que describir cada línea de segmento o cada curva.
TutorJava recomienda...
En esta página:
● Texto en Java 2D
❍ Fuentes
❍ Distribución 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 estática, podemos dibujarla directamente a través de
Graphics2D usando el método drawString. Para especificar la fuente, podemos usar el método
setFont de Graphics2D.
Si queremos implementar nuestras propias rutinas de edición de texto o necesitamos más control
sobre la distribucción 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 combinación de caracteres podría ser representada como uno o más
glyphs. Por ejemplo, á podría ser representado por dos glyphs, mientras que la ligadura fi podría
ser representada por un sólo glyph.
Se puede pensar en una fuente como en una colección de glyphs. Una sola fuente podría tener
muchas caras, como pesada, média, oblíqua, gótica y regular, Todas las caras de una fuente tienen
características tipográficas similares y pueden ser reconocidas como miembros de la misma familia.
En otras palabras, una colección de glyphs con un estilo particular forma una cara de fuente; y
una colección 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 método estático
GraphicsEnvironment.getLocalGraphicsEnvironment y preguntando al GraphicsEnvironment
devuelto. El método 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 también describe la colección de dispositivos de dibujo de la plataforma,
como pantallas e impresoras, que un programa Java puede utilizar. Esta información es usada
cuando el sistema realiza la conversión del espacio de usuario al espacio de dispositivo durante el
dibujo.
Nota:
En el JDK 1.1, las fuentes se describían con nombres lógicos que eran mapeados en diferentes
caras de fuentes, dependiendo de las fuentes que estaban disponibles en una plataforma
particular. Por razones de compatibilidad, Graphics2D también soporta la especificación de
fuentes por el nombre lógico. Para obtener una lista de los nombres lógicos de la fuentes, se
puede llamar a java.awt.Toolkit.getFontList.
Distribución 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 distribución de texto por nosotros. JTextComponent
soporta texto bidireccional y está diseñada para manejar las necesidades de la mayoría de las
aplicaciones internacionales. Para más información sobre el uso de los componentes de texto Swing,
puedes ver Usar Componentes de Texto.
En esta página:
● Imágenes
Imágenes
El API 2D de Java implementa un nuevo modelo de imagen que soporta la manipulación de
imágenes de resolución 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 gráficos son dibujados fuera de la pantalla en el
BufferedImage y luego son copiados a la pantalla a través de llamadas al método drawImage de
Graphics2D. Las clases BufferedImage y BufferedImageOp también permiten realizar una gran
variedad de operaciones de filtrado de imágenes como blur. El modelo de imagen
productor/consumidor proporcionado en las versiones anteriores del JDK sigue siendo soportado por
razones de compatibilidad.
TutorJava recomienda...
En esta página:
● Impresión
Impresión
Todos los gráficos del AWT y de Java 2D, incluidos los gráficos compuestos y las imágenes, pueden
ser dibujadas en una impresora usando el API de Java 2D. Este API proporciona características de
composición de documentos que nos permite realizar dichas operaciones como cambiar el orden de
impresión de las páginas.
En esta página:
● Mostrar Gráficos con Graphics2D
En esta página:
● Punteado y Relleno de Gráficos Primitivos
❍ Dibujar Curvas
❍ Ejemplo: Quad
❍ Ejemplo: Cubic
❍ Dibujar formas arbitrarias
❍ Ejemplo: Odd_Shape
❍ Definir Estilos de línea divertidos y Patrones de relleno.
❍ Estilos de Línea
❍ Patrón de Relleno
❍ Ejemplo: StrokeAndFill
El siguiente applet demuestra cómo podemos dibujar formas geométricas usando los métodos
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.
Cada una de las formas dibujadas por el applet está construida de geometrías y está dibujada a
través 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 formación 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));
polygon.closePath();
g2.draw(polygon);
// 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));
};
filledPolygon.closePath();
g2.setPaint(red);
g2.fill(filledPolygon);
Observa que este ejemplo usa implementaciones de doble precision de las clases geométricas.
Donde sea posible, las implementaciones de los float y doble precisión de cada geométrico están
proporcionados por clases internas.
Dibujar Curvas
Los applets Cubic y Quad demuestran como crear curvas cúbicas y cuadráticas usando
CubicCurve2D y QuadCurve2D. Estos applets también 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 cuadrática, 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.
Primero se crea una nueva curva cuadrática con dos puntos finales y un punto de control y las
posiciones de los puntos se seleccionan con respecto al tamaño de la ventana.
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á.
Una curva cúbica se crea con dos puntos finales y dos puntos de control y las localizaciones de los
puntos se seleccionan con respecto al tamaño de la ventana.
...
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.
Ejemplo: Odd_Shape
El ejemplo Odd_Shape usa GeneralPath para crear formas arbitrarias en la sección 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.
x2 = x;
y2 = y;
oddShape.moveTo(x, y);
Después de añadir el primer punto al path, se añaden tres líneas rectas.
x -= 100;
oddShape.lineTo(x, y);
y += 50;
oddShape.lineTo(x, y);
x += 100;
oddShape.lineTo(x, y);
Finalmente, se añade una curva cúbica.
x += 10;
y -= 10;
x1 = x - 20;
y1 = y - 20;
oddShape.curveTo(x, y, x1, y1, x2, y2);
Definir Estilos de línea divertidos y Patrones de relleno.
Probablemente habrás observado en el ejemplo anterior algunas de las formas tienen líneas
punteadas o están rellenas con gradientes de dos colores. Usando las clases Stroke y Paint de
Java 2D, podemos fácilmente definir estilos de línea divertidos y patrones de relleno.
Estilos de Línea
Los estilos de línea están definidos por el atributo stroke en el contexto Graphics2D. Para
seleccionar el atributo stroke podemos crear un objeto BasicStroke y pasarlo dentro del método
Graphics2D setStroke.
Un objeto BasicStroke contiene información sobre la anchura de la línea, estilo de uniones, estilos
finales, y estilo de punteado. Esta información se usa cuando se dibuja un Shape con el método
draw.
JOIN_BEVEL
JOIN_MITER
JOIN_ROUND
CAP_BUTT
CAP_ROUND
CAP_SQUARE
El estilo de punteado define el patrón de las secciones opacas y transparentes aplicadas a lo largo
de la longitud de la línea. Este estilo está definido por un array de punteado y una fase de
punteado. El array de punteado define el patrón 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 patrón de punteado, también
especificado en unidades de coordenadas de usuario. La fase de punteado indica que parte del
patrón de punteado se aplica al principio de la línea.
Patrón de Relleno
Los patrones de rellenos están 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 método 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 posición inicial y un color y una posición final y otro
color. El gradiente cambia proporcionalmente desde un color al otro a lo largo de la línea que
conecta las dos posiciones.
El patrón para una TexturePaint esta definido por un BufferedImage. Para crear un
TexturePaint, se especifica una imagen que contiene el patrón y un rectángulo que se usa para
replicar y anclar el patrón.
Ejemplo: StrokeAndFill
El applet StrokeAndFill permite al usuario seleccionar un gráfico primitivo, un estilo de línea, 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.
Los primitivos son inicializados e introducidos en un array de objetos Shape. El siguiente código
crea un Rectangle y un Ellipse2D.Double y los introduce en el array shapes.
Shape shape =
shapes[Transform.primitive.getSelectedIndex()];
Cómo se realiza el dibujo dependen de las opciones elegidas.
● Cuando el usuario elige stroke, se llama a Graphics2D.draw para realizar el dibujo, Si se elige text
como primitivo, las líneas son recuperadas y el dibujo se hace con el método 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 línea exterior.
Nota:
Para rellenar y puntear un gráfico primitivo, necesitamos hacer dos llamadas separadas a
métodos: fill o drawString para rellenar el interior, y draw para dibujar el exterior.
Los tres estilos de línea usados en este ejemplo -- ancho, estrecho y punteado -- son ejemplares de
BasicStroke.
En este ejemplo se usan tres estilos de dibujo -- sólido, gradiente y polka. El dibujo de color sólido
es un ejemplar de Color, el gradiente un ejemplar de GradientPaint, y el patrón un ejemplar de
TexturePaint.
En esta página:
● Transformar Formas, Texto e Imágenes
❍ Ejemplo: Transform
Graphics2D proporciona varios métodos para cambiar el atributo transform. Podemos construir un
nuevo AffineTransform y cambiar el atributo transform de Graphics2D llamando al método
setTransform.
AffineTransform define los siguientes métodos para hacer más sencilla la construcción de nuevas
transformaciones:
● getRotateInstance
● getScaleInstance
● getShearInstance
● getTranslateInstance
De forma alternativa podemos usar uno de los métodos de transformación de Graphics2D para
modificar la transformación actual. Cuando se llama a uno de esos métodos de conveniencia, la
transformación resultante se concatena con la transformación actual y es aplicada durante el
dibujado.
● rotate--para especificar un ángulo de rotación en radianes.
● scale--para especificar un factor de escala en direcciones x e y.
● shear--para especificar un factor de compartición en direcciones x e y
● translate--para especificar un desplazamiento de movimiento en direcciones x e y
También podemos construir directamente un AffineTransform y concatenarlo con la
transformación actual llamando al método transform .
Ejemplo: Transform
El siguiente programa es el mismo que StrokeandFill, pero también permite al usuario elegir una
transformación 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.
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...
En esta página:
● Recortar la Región de Dibujo
❍ Ejemplo: ClipImage
❍ Ejemplo: Starry
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 código de este applet. El applet requiere el fichero de imagen
clouds.jpg.
El path de recortado está definido por la intersección de una elipse y un rectángulo cuyas
dimensiones son aleatorias. La elipse se pasa al método setClip , y luego se llama al método clip
para seleccionar el path de recortado a la intersección entre la elipse y el rectángulo.
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 código completo de este programa. El applet requiere el fichero de imagen
Starry.gif.
TutorJava recomienda...
En esta página:
● Componer Gráficos
❍ Ejemplo: Composite
Componer Gráficos
La clase AlphaComposite encapsula varios estilos de composición, que determinan cómo se
dibujan los objetos solapados. Un AlphaComposite también 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 composición 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 posición que los pixels renderizados préviamente
(el destino), los pixels de la fuente se renderizan sobre los pixels
del destino.
Source-in (SRC_IN)
Source-out (SRC_OUT)
Destination-over (DST_OVER)
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 borrarán.
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 borrarán.
Clear (CLEAR)
Para cambiar el estilo de composición usado por Graphics2D, creamos un objeto AlphaComposite
y lo pasamos al método setComposite.
Ejemplo: Composite
Este programa ilustra los efectos de varias combinaciones de estilos de composición 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.
AlphaComposite ac =
AlphaComposite.getInstance(AlphaComposite.SRC);
Cuando se selecciona una regla de composición 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 parámetro 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 más tarde se copian
en la pantalla, por eso el atributo composite se configura con el contexto Graphics2D para el
BufferedImage.
En esta página:
● Controlar la Calidad del Dibujo
No todas las plataformas soportan la modificación del modo de dibujo, por eso el especificar los
hints de dibujo no garantiza que sean utilizados.
En esta página:
● Construir Formas Complejas desde Geométricos Primitivos
❍ Ejemplo: Areas
Unión Subtracción
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.
Las hojas son creadas realizando una interesección entre dos círculos solapados:
En esta página:
● Soportar Interacción con el Usuario
❍ Ejemplo: ShapeMover
❍ Ejemplo: HitTestSample
Si estamos usando texto primitvo, podemos realizar una simple comprobación obteniendo la línea
exterior de la Shape que corresponde al texto y luego llamando a hit o contains con esa Shape.
El soporte de edición de texto requiere una comprobación mucho más sofisticada. Si queremos
permitir que el usuario edite el texto, generalmente deberíamos 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 posición del texto, también podemos usar TextLayout para realizar la
comprobación para la edición de texto. Para más información 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 posición del ratón para proporcionar información 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.
Se llama al método contains para determinar si el cursor está dentro de los límites del rectángulo
cuando se pulsa el botón. Si es así, se actualiza la posición del rectángulo.
Ejemplo: HitTestSample
Esta aplicación ilustra la comprobación 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.
...
private Point2D computeLayoutOrigin() {
Dimension size = getPreferredSize();
Point2D.Float origin = new Point2D.Float();
...
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);
...
private class HitTestMouseListener extends MouseAdapter {
/**
* Compute the character position of the mouse click.
*/
public void mouseClicked(MouseEvent e) {
En esta página:
● Trabajar con Texto y Fuentes
❍ Crear y Derivar Fuentes
❍ Dibujar Múltiples Líneas de Texto
En esta página:
● Crear y Derivar Fuentes
❍ Ejemplo: FontSelection
Ejemplo: FontSelection
El siguiente applet nos permite cambiar la fuente, el tamaño 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.
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 tamaño 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 tamaño.
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
método 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 método 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 podría no funcionar de forma apropiada con todos los
nombres de fuentes devueltos por la llamada a getFontFamilyNames. La forma podría no
corresponder con cambios en el tamaño o el estilo y el texto podría no mostrarse cuando se
selecionan algunos nombres de fuentes. En general, Courier y Helvetica funcionan bien. Mientras
tanto, compruebalo periódicamente para ver si se han resuelto estos problemas.
TutorJava recomienda...
En esta página:
● Dibujar Múltiples Líneas de Texto
❍ Ejemplo: LineBreakSample
Ejemplo: LineBreakSample
El siguiente applet posiciona un párrafo 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 siguiente código crea un bucle con la cadena vanGogh. El inicio y final del bucle se recupera y se
crea una nueva línea.
En esta página:
● Mostrar y Manipular Imágenes
❍ Modo Inmediato con BufferedImage
❍ Filtrado y BufferedImage
❍ Usar un BufferedImage para doble buffer
Filtrado y BufferedImage
Esta sección muestra cómo usar las clases BufferedImageOp para realizar operaciones de filtrado
sobre BufferedImage.
En esta página:
● Modo Inmediato con BufferedImage
BufferedImage es la clase clave del API del modo-inmediato. Esta clase maneja una imagen en
memoria y proporciona métodos para almacenar, interpretar y dibujar cada dato de pixel. Un
BufferedImage puede ser renderizado en un contexto Graphics o on un contexto Graphics2D.
El ColorModel proporciona una interpretación 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 múltiples subimagenes de un sólo buffer de
imagen. El Raster también proporciona métodos para acceder a pixels específicos dentro de la
imagen. Para más información sobre como manipular directamente los datos de los pixels y escribir
filtros para objetos BufferedImage, puedes ver el capítulo Imaging de Java 2D Programmer's
Guide.
TutorJava recomienda...
En esta página:
● Filtrar un BufferedImage
❍ Ejemplo: ImageOps
Filtrar un BufferedImage
El API Java 2D define varias operaciones de filtrado para objetos BufferedImage . Cada operación
de proceso de imágenes está incluida en una clase que implementa el interface BufferedImageOp.
La manipulación de imágenes se realiza en el método filter. La clase BufferedImageOp en el API
Java 2D soporta:
● Tranformación afin.
● Escalado.
● Modificación de Aspecto.
● Combinación Linear de Bandas.
● Conversión de color.
● Convolución.
Para filtrar un BufferedImage usando una de las clases de operación de imagen, debemos
1. Constuir un ejemplar de una de las clases BufferedImageOp: AffineTransformOp,
BandCombineOp, ColorConvertOp, ConvolveOp, LookupOp , o RescaleOp.
2. Llamar al método de operación 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 código 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. Convolución es el proceso de hacer más pesado
el valor de cada pixel en una imagen con los valores de los pixels vecinos. La mayoría de los
algoritmos de filtrado espacial estan basados en las operaciones de convolución.
Para construir y aplicar este tipo de filtrado al BufferedImage, este ejemplo usa un código similar
al del siguiente fragmento.
En esta página:
● Usar un BufferedImage para Doble Buffer
❍ Ejemplo: BufferedShapeMover
Cuando dibujamos sobre un componente Swing, éste utiliza automáticamente el doble buffer.
Un BufferedImage puede usarse fácilmente como un buffer fuera de pantalla. Para crear un
BufferedImage cuyo espacio, color, profundidad y distribución de pixels corresponden
exactamente la ventana en la que son dibujados, se llama al método 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.
Ejemplo: BufferedShapeMover
El siguiente applet permite al usuario arrastrar un rectángulo sobre la ventana del applet. En lugar
de dibujar el rectángulo en cada posición del cursor, para proporcionar información al usuario, se
usa un BufferedImage como buffer fuera de la pantalla. Cuando se arrastra el rectángulo, es
renderizado dentro del BufferedImage en cada nueva posición 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.
Aquí está el código usado para renderizar en el BufferedImage y mostrar la imagen en la pantalla.
En esta página:
● Imprimir en Java
❍ Introducción a la Impresión en Java
❍ Imprimir los Contenidos de un Componente
❍ Mostrar el diálogo 'Page Setup'
❍ Imprimir una Colección de Páginas
Imprimir en Java
Esta lección nos enseña cómo usar el API de Impresión de Java para imprimir desde nuestras
aplicaciones Java. Aprenderemos cómo dibujar los contenidos de nuestros componentes a la
impresora en lugar de al dispositivo de pantalla y como componer documentos de múltiples páginas.
Esta lección asume que has leido la primera lección de esta ruta, Introducción al API 2D de Java, y
que estás familiarizado con el uso del contexto de dibujo Graphics2D.
En esta página:
● Introducción a la Impresión en Java
❍ Job Control
❍ Imaging
❍ Printable Jobs
❍ Pageable Jobs
Este modelo de impresión 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 página completa. En
esta situación el sistema de impresión le pedirá a nuesta aplicación que renderize la página de
forma repetida para que pueda ser imprimida como una serie de pequeñas imágenes.
Para dirigir el PrinterJob a través del proceso de impresión, nuestra aplicación necesita
1. Obtener un PrinterJob llamando a PrinterJob.getPrinterJob
2. Decirle al PrinterJob dónde está el código de dibujo llamando a setPrintable o setPageable
3. Si se desea, mostrar los diálogos de configuración de página e impresión llamando a pageDialog y
printDialog
4. Iniciar la impresión llamando a print
El dibujo de páginas está controlado por el sistema de impresión a través de llamadas al código de
imágenes de la aplicación.
Imaging
Nuestra aplicación debe poder renderizar cualquier página cuando el sistema de impresión lo pida.
Este código de renderizado está contenido en el método print de un page painter--una clase que
implementa el interface Printable. Nosotros implementamos print para renderizar el contenido de
la página usando un Graphics o un Graphics2D. Podemos usar un único 'page painter' para
renderizar todas las páginas de un 'print job' o diferentes 'page painters' para los diferentes tipos de
páginas. Cuando el sistema de impresión necesita renderizar una página, llama al método 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 más sencilla de soportar impresión. Las operaciones de impresión más complejas
que usan múltiples '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 páginas usan el mismo 'page painter' y PageFormat, que define el
tamaño y orientación de la página a imprimir. Se le pide al 'page painter' que renderice cada página
en orden indexado, empezando en la página con índice 0. Al'page painter' se le podría pedir que
renderizará una página varias veces antes de pedir la siguiente página. Por ejemplo, si un usuario
quiere imprimir las páginas 2 y 3 de un documento, se le pide al 'page painter' que renderice las
páginas con índices 0,1 y 2 incluso aunque las dos primeras no sean impresas.
Pageable Jobs
Los 'pageable jobs' son útiles si nuestra aplicación construye una representación explícita de un
documento, página por página. En un 'pageable job' diferentes páginas pueden usar diferentes
'page paintes' y PageFormats. El sistema de impresión puede pedir a los 'page painters' que
rendericen las páginas en cualquier orden, incluso puede saltarse algunas. Por ejemplo si un usuario
quiere imprimir las páginas 2 y 3 de un documento, sólo se le pedirá al 'page painter' que renderice
las páginas con los índices 1 y 2.
Los distintos 'page painteres' de un 'pageable job' están coordinados por una clase que implementa
el interface Pageable, como un Book. Un Book representa una colección de páginas que pueden
usar diferentes 'page painter' y que pueden variar en tamaño y orientación, También podemos usar
nuestra propia implementaciuón del interface Pageable si Book no cumple con las necesidades de
nuestra aplicación.
TutorJava recomienda...
En esta página:
● Imprimir los Contenidos de un Componente
❍ Ejemplo: ShapesPrint
Ejemplo: ShapesPrint
En este ejmplo usamos el mismo código de dibujo para mostrar e imprimir los contenidos de un
componente. Cuando el usuario pulsa sobre el botón print, se crea un 'print job' y se llama a
printDialog para mostrar el diálogo de impresión. Si el usuario contínua con el trabajo, el proceso
de impresión se inicia, y el sistema de impresión llama a print cuando sea necesario renderizar el
trabajo a la impresora.
ShapesPrint es el 'page painter'. Su método print llama a drawShapes para realizar el dibujo del
'print job'. (También se llama al método drawShapes por parte de paintComponent para dibujar
en la pantalla.)
En esta página:
● Mostrar el Diálogo de Configuración de Página
ShapesPrint podría fácilmente ser modificado para mostrar un diálogo de configuración de página
añadiendo una llamada a pageDialog después 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...
En esta página:
● Imprimir una Colección de Páginas
❍ Ejemplo: SimpleBook
Ejemplo: SimpleBook
El programa SimpleBook usa un Book para manejar dos 'page painters': PaintCover se utiliza
para la cubierta, y PaintContent para la página de contenido. La cubierta se imprime en modo
apaisado, mientras que el contenido se imprime en modo vertical.
Una vez creado el Book, las páginas se añaden con el método append. Cuando se añade una
página a un Book, se necesita especificar el Printable y el PageFormat para usar con cada
página.
// Set up a book
Book bk = new Book();
bk.append(new PaintCover(), job.defaultPage());
bk.append(new PaintContent(), landscape);
En esta página:
● Problemas Más Comunes en los Gráficos en Java 2D
Problema: ¿Cómo puedo escribir sobre una imagen anterior? Nuestro problema es que nuestro applet muestra una imagen
de un mapa, pero cuando se dibuja una línea sobre el mapa, la línea sobreescribe el mapa.
● Deberías intentar dibujar tu imagen dentro de un BufferedImage. Luego, dibuja el BufferedImage dentro de un contexto
Graphics2D y luego dibuja la línea sobre el contexto Graphics2D un ejemplo de código está en Map_Line.java Sólo debes
sustituir el nombre de tu imagen por images/bld.jpg.
Problema: ¿Cómo creo un BufferedImage desde un fichero gif o jpeg?
● 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 código ilustra esto.
Necesitas crear un contexto Graphics2D para el BufferedImage usando el método createGraphics. Luego, puedes
usar el método drawImage de la clase Graphics2D para dibujar la imagen dentro del buffer.
Podrías usar drawString para dibujar el texto en el contexto Graphics2D y luego llamar a g2.rotate (ángulo de
rotación). Esto rotará todo lo que hayamos introducido dentro del contexto Graphics2D. Por eso, podríamos 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: He leido su comentario en la parte inferior de Crear y Derivar fuentes sobre el bug 4155852. Este bug ha sido
cerrado sin ninguna acción. ¿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 físicas (como Arial o
Palatino). Sólo se pueden aplicar estilos a las fuentes lógicas en este momento (como Dialog o SansSerif).
Como atajo hasta que se corrija el bug, podrías hacer lo siguiente:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import 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.
*/
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;
}
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 x = 5;
int y = 7;
int rectWidth = gridWidth - 2*x;
int stringY = gridHeight - 3 - fontMetrics.getDescent();
int 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;
g2.draw(polygon);
g2.drawString("GeneralPath", x, stringY);
// NEW ROW
x = 5;
y += gridHeight;
stringY += gridHeight;
g2.draw(polyline);
g2.drawString("GeneralPath (open)", 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);
}
}
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.applet.Applet;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
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);
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;
}
}
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;
}
}
checkPoint();
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;
}
}
/*
* 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((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 java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.applet.Applet;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
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);
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;
}
}
checkPoint();
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;
}
}
/*
* 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((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 java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
public OddPanel(){
oddShape = new GeneralPath();
firstTime = true;
area = new Rectangle();
}
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 1.2 98/07/31
*/
import java.lang.Integer;
import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;
import 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.
*/
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);
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);
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);
validate();
applet.init();
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);
}
if ( !StrokeAndFill.no2D ) {
Graphics2D g2 = (Graphics2D) g;
Dimension d = getSize();
w = d.width;
h = d.height;
int width, height;
} else {
g.drawRect(0, 0, 100, 100);
}
}}
/*
* @(#)Transform.java 1.2 98/07/31
*/
import java.lang.Integer;
import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.*;
/*
* This applet renders a shape, selected by the user, with a paint,stroke, and
rendering method,
* also selected by the user.
*/
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);
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);
ls.gridwidth = GridBagConstraints.RELATIVE;
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);
validate();
applet.init();
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);
}
if ( !Transform.no2D ) {
Graphics2D g2 = (Graphics2D) g;
Dimension d = getSize();
w = d.width;
h = d.height;
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;
}
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;
}
g2.transform(toCenterAt);
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 javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.event.WindowAdapter;
import java.awt.image.BufferedImage;
import java.net.URL;
/**
* Animated clipping of an image & shapes with alpha.
*/
public class ClipImage extends JApplet implements Runnable {
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;
}
g2.drawImage(img, 0, 0, w, h, this);
p.reset();
p.moveTo(- w / 2.0f, - h / 8.0f);
p.lineTo(+ w / 2.0f, - h / 8.0f);
p.lineTo(- w / 4.0f, + h / 2.0f);
p.lineTo(+ 0.0f, - h / 2.0f);
p.lineTo(+ w / 4.0f, + h / 2.0f);
p.closePath();
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);
}
}
}
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;
}
w = getWidth();
h = getHeight();
if ( w <= 0 || h <= 0 )
return;
Graphics2D g2 = createDemoGraphics2D(g);
drawDemo(g2);
g2.dispose();
newBufferedImage = false;
}
Thread me = Thread.currentThread();
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;
}
import java.net.URL;
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;
}
f.getContentPane().add(starPanel, BorderLayout.CENTER);
f.setSize(new Dimension(550, 200));
f.setVisible(true);
}
}
Image img;
int w, h;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
}
}
/*
* @(#)Composite.java 1.2 98/07/31
*/
import java.lang.Integer;
import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.geom.*;
import 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.
*/
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);
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);
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;
}
AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC);
float alpha = 1.0f;
public CompPanel(){}
Dimension d = getSize();
int w = d.width;
int h = d.height;
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
import 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.
*/
setLayout(new BorderLayout());
add(new SMCanvas());
// 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);
// 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();
repaint();
}
if(firstTime){
area = new Rectangle(dim);
rect.setLocation(w/2-50, h/2-25);
firstTime = false;
}
/*
* 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((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 javax.swing.*;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.font.TextHitInfo;
import java.awt.font.TextLayout;
import java.awt.geom.Point2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.AttributedCharacterIterator;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.awt.font.TextAttribute;
import java.util.Hashtable;
import 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 {
HitPane hitPane;
// Initilize insertionIndex.
insertionIndex = 0;
/**
* 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() {
/**
* 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;
graphics2D.translate(origin.getX(), origin.getY());
// Draw textLayout.
textLayout.draw(graphics2D, 0, 0);
if (carets[1] != null) {
graphics2D.setColor(WEAK_CARET_COLOR);
graphics2D.draw(carets[1]);
}
}
/**
* Compute the character position of the mouse click.
*/
public void mouseClicked(MouseEvent e) {
sampleFrame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
import java.lang.Integer;
import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Vector;
/*
* This applet displays a String with the user's selected
* fontname, style and size attributes.
*/
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);
/*
* 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;
}
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);
}
Font thisFont;
public FontPanel(){
thisFont = new Font("Arial", Font.PLAIN, 10);
}
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 javax.swing.*;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextLayout;
import java.util.Hashtable;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.awt.font.TextAttribute;
import java.awt.event.WindowAdapter;
import 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 LineBreakPanel() {
AttributedCharacterIterator paragraph = vanGogh.getIterator();
paragraphStart = paragraph.getBeginIndex();
paragraphEnd = paragraph.getEndIndex();
super.paintComponent(g);
setBackground(Color.white);
float drawPosY = 0;
lineMeasurer.setPosition(paragraphStart);
}
}
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.image.*;
import java.awt.geom.AffineTransform;
import java.awt.font.TextLayout;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.event.WindowAdapter;
import java.net.URL;
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);
}
}
g2.setColor(Color.black);
float[][] data = {{0.1f, 0.1f, 0.1f, // low-pass filter
0.1f, 0.2f, 0.1f,
0.1f, 0.1f, 0.1f},
SHARPEN3x3_3};
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);
}
}
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;
}
}
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
import java.awt.image.*;
// 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);
// Handles the event of the user pressing down the mouse button.
public void mousePressed(MouseEvent e){
// 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.");
}
}
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;
}
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 java.awt.geom.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.print.PrinterJob;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import java.awt.print.*;
public ShapesPrint() {
setBackground(bg);
button.addActionListener(this);
}
int rowspacing = 5;
int columnspacing = 7;
int rectWidth = gridWidth - columnspacing;
int rectHeight = gridHeight - rowspacing;
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(polygon);
// NEW ROW
x = 85;
y += gridHeight;
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);
}
}
import java.awt.event.*;
import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.*;
import java.awt.geom.*;
import java.awt.print.*;
public SimpleBook() {
setBackground(bg);
button.addActionListener(this);
}
// 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 */ }
}
}
int rowspacing = 5;
int columnspacing = 7;
int rectWidth = gridWidth - columnspacing;
int rectHeight = gridHeight - rowspacing;
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;
// 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(polygon);
// NEW ROW
x = 85;
y += gridHeight;
g2.draw(polyline);
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());
}