Gráficas e imágenes con Java GRAFICAS DE 2D ELEMENTOS BÁSICOS DE GRAFICAS 2D. El píxel es elemento atómico de una imagen o gráfico en dos dimensiones. El manejo del píxel es fundamental en los sistemas de gráficas basados en rastreo de líneas de mapa de memoria, es y ha sido una técnica muy favorecida por las fábricas que construyen monitores y televisores digitales en colores como ya vimos en el capitulo anterior. El píxel es pues el inicio de todo en cuanto a lasgráficas por computadora se refiere, siendo este el punto de arranque para construir métodos de dibujo de elementos primordiales o primitivos en una gráfica de dos dimensiones. A continuación mostramos una lista con lo fundamental para empezar a construir un sistema de gráficos 2D en computadora. Línea recta Polígonos Curvas cónicas Relleno de superficies Curvas con interpolación polinomial Texto Anti-alias Trazado de líneas rectas Lo que pudiera parecer como un trabajo sencillo y rápido de hacer, se vuelve complicado tan pronto como intentamos tratar de implementar la clásica ecuación de la recta, en un campo numérico finito. El problema es que por mas pequeñas que sean las dimensiones en pantalla del píxel, nunca habrá un número infinito de ellos y por lo tanto tampoco habrá una cantidad infinita de memoria para video que respaldara tal cantidad de información; por lo que en términos prácticos, es mejor olvidarse del tratamiento numérico de las rectas con el campo de los números reales. Gráficas e imágenes con Java Entre el cero y el uno, existe infinito número de cifras y al contrario, en pantalla no existe infinito número de pixel´s. Sin embargo podemos intentar algunas estrategias Gráficas e imágenes con Java Para fin de darle la vuelta a ese problema matemático y físicamente técnico. En primer lugar intentaremos aplicar el simple redondeo a la fuerza bruta de la ecuación clásica de la recta en geometría analítica. Gráficas e imágenes con Java Podemos ver claramente que con el método tradicional para la recta encontramos un par de operaciones aritméticas que involucran números reales, con ello queda desechado este método, pues en el redondeo aparece el error y aquí vemos dos acciones con números reales. Sin embargo podemos emplear una aproximción ligeramente diferente al método de la geometría analítica clásico, usando a la propia pendiente de la recta, tal es el método DDA, del inglés Digital Differential Analizer. El método basado en el análisis digital (o discreto ) de diferencias se ocupa de modificar el cálculo subsiguiente del par X e Y de un punto sobre la recta a dibujar en pantalla, en función de la magnitud de su pendiente. Con DDA se distinguen cinco casos para dibujar la recta en términos de la pendiente: Gráficas e imágenes con Java Gráficas e imágenes con Java El método basado en el DDA es un poco más rápido que el clásico, pues elimina la multiplicación de numeros reales y sólo se queda con la suma de un entero contra un real. Ciertamente sigue siendo necesario el redondeo y por ese motivo puede que no sea considerado como el óptimo método para trazar rectas. Sin embargo una variante del método de análisis de diferencias nos conduce a una forma muy interesante de calcular puntos intermedios para graficar curvas arbitrarias, y todo ello basado en el conocido concepto de la derivada. Uno de los principales atractivos de los algoritmos derivados del DDA, es sin duda su simplicidad y por lo tanto su relativamente fácil camino a la implementación. Como quiera que sea, sería mejor implementar una solución basada en operaciones de números enteros con el fin de no requerir la operación de redondeo y por lo tanto evitar la propagación del error aritmético. En este punto debemos reconocer que los procesadores numéricos hoy día son muchísimas veces mas eficientes y con mayor precisión que aquellos de hace dos décadas, vamos pues, microprocesadores del siglo pasado, de la 3ª generación. Hoy por hoy los procesadores gráficos requieren de un apoyo intenso de operaciones con números reales, por ejemplo la serie Quadro FX de Nvidia, cuentan con operaciones de punto flotante de precisión sencilla ( FX 570 y FX 370). Funcionamiento similar encontramos la serie Xpress del chip Radeon de Ati; por ejemplo el Radeon Xpress 1100 o el Xpress 200. En el siguiente método de trazado de rectas apreciaremos en lo que vale, el esfuerzo que se hace para eliminar las operaciones con números reales. El método propone el empleo de un par de rectas virtuales, que siempre “pasan” sobre la representación entera del píxel en memoria. La cosa, es que se tiene que decidir por cual recta nos inclinamos para escoger el píxel correspondiente. Gráficas e imágenes con Java Este es el conocido método de Bresenham, y se basa en operaciones de aritmética con números enteros. Las rectas virtuales contienen el siguiente punto a dibujar, es decir, usando sólo enteros, como en realidad manejaríamos las direcciones de memoria de video. Pero de las dos opciones a dibujar una es la mejor, y ello depende de ver cual recta virtual está más próxima a la recta propuesta o en su caso, recta teórica. No es un problema trivial que podamos alegremente pasar por alto; vamos a suponer que deseamos dibujar en pantalla una escena basada en una familia de polígonos ( algo muy común en diseño gráfico ), no podemos permitir que las rectas que forman las aristas de los polígonos tengan huecos o discontinuidades, ello daría al traste con el relleno de colores para cada polígono, pues el relleno de estos, requiere de una frontera continua para determinar la superficie visible de cada polígono, de tal manera que no se produzca una invasión de color entre figuras geométricas vecinas. Un beneficio adicional y muy importante para la gestión del sistema, es que con las fronteras bien delimitadas se puede calcular con precisión el volumen de memoria requerido para almacenar las imágenes. El método de Bresenham se basa en operaciones con enteros, y su principio es el del mero conocimiento de los puntos inicial y final. Así que por lo menos tenemos un comienzo firme; el parámetro que nos permite inclinar la decisión por un siguiente punto particular (P[n+1]), sobre la recta virtual superior o inferior, es la diferencia de las distancias, d1 contra d2, dicha diferencia la llamaremos simplemente parámetro de decisión o P. Para el caso que se presenta, si P es menor a cero, significa que la recta superior es más cercana a la teórica que la inferior, por lo que el siguiente punto simplemente sería: Gráficas e imágenes con Java donde y[n] es la ordenada actual al tiempo del cálculo, y y[n+1] es la siguiente ordenada. En otro caso, si P es mayor a cero, implica que el siguiente punto sería: A continuación, los cálculos a seguir para determinar los pixel´s de la recta a visualizar. Calculo de Bresenham: Para calcular la recta: 1.- entramos las coordenadas (xi,yi) y (xf,yf) correspondientes a los puntos inicial Y final …pi, pf 2.- determinamos la magnitud de m, para el caso m<1: 3.- calculamos el parámetro de decisión “P”: 4.- determinamos el siguiente punto en base a “P”: *la última operación puede valer 0 o 1, lo que simplifica el subsiguiente cálculo. p0 2y x 5.- si P < 0 entonces: y n 1 y n 1 pn1 pn 2y 2x 6.- otro caso P>0 entonces: Gráficas e imágenes con Java y n 1 y n pn1 pn 2y 7.- repetir desde (5) hasta que: x n 1 xf Lo anterior aplica para rectas con pendientes mayores a cero pero menores a la unidad, para pendientes mayores a la unidad, simplemente intercambiamos el papel que juegan x e y. Ahora veamos un ejemplo: A continuación, código de JAVA que ayuda a calcular los puntos a visualizar de una recta determinada por dos puntos. La entrada al programa es pues el punto inicial y final de una recta. El código principal se localiza en el directorio bresh.prim. package bresh.prim; public class BresLinea { //atributos de la clase private int xi,xf,yi,yf; private int deltax, deltay; private int dosX, dosY; protected int temp, p; //constructor de prueba public BresLinea(){xi=0;xf=10;yi=0;yf=10;iniC();} Gráficas e imágenes con Java //constructor general public BresLinea(int x1,int y1, int x2, int y2){xi=x1;xf=x2;yi=y1;yf=y2;iniC();} //determina si m<1 o m<1 private void iniC(){ double dx;double dy; dx=Math.abs(xf-xi); dy=Math.abs(yf-yi); if(dy>dx){calcaY();} else {calcaX();} } // cálculo de X private void calcaX(){ if(xi>xf){ temp=xf; xf=xi; xi=temp; temp=yf; yf=yi; yi=temp; } deltax=xf-xi;deltay=yf-yi; dosX=2*deltax;dosY=2*deltay; System.out.println("X = :"+xi+" ; Y = :"+yi); p=dosY-deltax; xi++; while(xi<xf){ if(p>0){ p=p+dosY-dosX; yi++; } else{ p=p+dosY; } System.out.println(“P= > "+p” ; X = :"+xi+" ; Y = :"+yi); xi++; }} //cálculo de Y private void calcaY(){ if(yi>yf){ temp=xf; xf=xi; xi=temp; temp=yf; yf=yi; yi=temp; } deltax=xf-xi;deltay=yf-yi; dosX=2*deltax;dosY=2*deltay; System.out.println("X = :"+xi+" ; Y = :"+yi); p=dosX-deltay; Gráficas e imágenes con Java yi++; while(yi<yf){ if(p>0){ p=p+dosX-dosY; xi++; } else{ p=p+dosX; } System.out.println("X = :"+xi+" ; Y = :"+yi); yi++; }} } Los polígonos Una vez que podemos trazar rectas continuas en la pantalla, ya podemos pasar a crear figuras compuestas por segmentos abiertos de recta y por polígonos. Ello es posible mediante la implementación de un arreglo de rectas.; posteriormente “pasar” los elementos de dicho arreglo al método de trazado de rectas. Por ejemplo en la API de JAVA 2D tenemos a la importantísima interfaz Shape, con la cual se implementan una variedad de clases para gráficas en 2D, para el caso que nos ocupa, Rectangle2D, Polygon, en relación a figuras cerradas, pero también podemos tener figuras abiertas con GeneralPath. En la mayoría de las ocasiones, cuando se desea implementar una serie de escenas o paisajes en algún juego por computadora, se prefiere el uso de polígonos para crear superficies, estas se pueden iluminar de manera sencilla y sobre todo rápida. Muchos paisajes pueden crearse en base al polígono mas simple… el triángulo. En JAVA esto es muy sencillo, si nos apoyamos en la API 2D ya incorporada. Sin embargo para completar la salida del siguiente ejemplo, observamos que al generar líneas rectas le podemos asociar algunas cualidades que son de utilidad para crear dibujos con mejor contenido. Por ejemplo a las rectas con todo y polígonos, les podemos colgar algunas otras cualidades deseables. Color de la línea o arista. Grosor de de la recta. Patrón de despliegue. Terminado de vértices de polígonos. Sobre todo eso último era de impacto en los tiempos en que los monitores soportaban bajas resoluciones, pues en ciertas situaciones los vértices aparentaban terminados extraños, por ejemplo, cuadros triángulos…etc. Curvas cónicas Gráficas e imágenes con Java La circunferencia y la elipse son figuras básicas en las gráficas por computadora y forman una familia de curvas basadas en polinomios de segundo grado; las llamadas “curvas cónicas” desde los tiempos de Apolonio(262-190 AC). Esta clase curvas ha sido un pilar muy importante en diversas actividades de la humanidad. Podría decirse que el estudio detallado de las curvas cónicas y sus implicaciones en la física clásica han llevado al Hombre a la Luna y en un sentido mas extenso, a conquistar los misterios del Sistema Solar, tal vez algún día en el lejano futuro, las curvas cónicas nos lleven a las estrellas. Tal vez el matemático griego Maneco(375 -325 AC) contemporáneo del Filósofo Platón, descubrió en principio las curvas cónicas, pero fue Apolunio quien realizó los primeros estudios de tales curvas de manera profunda y sobre todo, documentada. Los aficionados a la astronomía le agradecemos grandemente a Apolonio por su estudio de las cónicas. Apolonio encontró que si despliega una fuente de luz en el foco de un espejo con sección elíptica, entonces la luz reflejada en el espejo conduce a un punto preciso que representa el otro foco. Si se recibe luz de una fuente lejana (para fines prácticos una fuente con rayos paralelos al eje de giro de la sección de espejo) con sección parabólica, entonces la luz reflejada por el espejo se concentra en el foco; desde luego esto nos recuerda invariablemente al principio de funcionamiento del telescopio reflector de Newton. Esta propiedad permite encender un papel si se coloca en el foco de un espejo parabólico y el eje del espejo se apunta hacia el sol. Existe la leyenda de que Arquímedes (287-212 A.C.) logró incendiar las naves romanas durante la defensa de Siracusa usando las propiedades de los espejos parabólicos. Actualmente esta propiedad se utiliza en los radares, las antenas de televisión y espejos solares. La propiedad análoga, que nos dice que un rayo que parte del foco se refleja paralelamente al eje sirve para que los faros de los automóviles concentren el haz en la dirección de la carretera o para estufas. En el caso de los espejos hiperbólicos, la luz proveniente de uno de los focos se refleja como si emanara del otro foco. En el siglo XVI el filósofo y matemático René Descartes (1596-1650) desarrolló un método para relacionar las curvas con ecuaciones. Este método es la llamada Geometría Analítica. En la Geometría Analítica las curvas cónicas se pueden representar por ecuaciones de segundo grado en las variables x e y. Gráficas e imágenes con Java Gráficas e imágenes con Java Presentamos la aplicación del método analizador diferencial a la circunferencia; aunque este se puede hacer extensivo fácilmente a la elipse. Para la exitosa ejecución de la implementación del método DDA a las curvas cónicas, sólo recordemos que a diferencia de el caso de la recta, acá la pendiente es dinámica. Gráficas e imágenes con Java El método DDA para la circunferencia y para la elipse resulta fácil de implementar, lamentablemente se tiene que recurrir al redondeo y como en el caso de la recta, ello ocasiona errores y sus consecuentes huecos en el trazado de la curva, con desastrosos resultados a la hora del relleno de las superficies “cerradas” por esta clase de curvas. Considerando la aritmética con números enteros, entonces recuperamos las ideas centrales del método de Bresenham para le recta y luego las aplicamos para la implementación del trazado de elipses y circunferencias y al fin de cuentas para las cónicas. La ecuaciones básicas de la circunferencia y de la elipse son: 2 x y R (xb) ( ya) 2 2 2 2 a 2 b 2 El método consiste en escoger un punto sobre alguna de las dos curvas hipotéticas que siguen a la curva propuesta, ambas curvas sólo difieren de la propuesta por medio píxel, entonces el factor que determina cual punto de que curva tomar para realizar el trazado es la menor distancia que exista entre las curvas hipotéticas y la propuesta para cada iteración. Un elemento que nos ayuda al trazado de la curva es el principio de simetría, que aplica perfectamente para las curvas cónicas. Además el hecho de que la derivada que determina la tangente a tales curvas es dinámica, pero siempre pasa por un punto en donde el valor de la pendiente de la recta tangente es -1, nos simplifica aun mas el cálculo de los puntos a trazar de las cónicas. En una parte del cálculo la pendiente es muy suave y cambia lentamente la ordenada, mientras que la abscisa cambia con mayor magnitud. En otra parte del cálculo cambia la situación y la pendiente aumenta, la ordenada cambia en mayor magnitud mientras que la abscisa cambia lentamente. El punto donde se separan los cálculos se localiza sobre la curva en donde la tangente tiene una pendiente igual a -1; esto es: dy dx 1 Gráficas e imágenes con Java Ahora seguimos con el desarrollo del método, tanto para la circunferencia como para la elipse, en ambos casos tratamos el cálculo del primer sector del primer cuadrante; para el caso es en el sentido de incrementar la abscisa y decrementar la ordenada hasta que la primera derivada es igual a -1. Partimos del punto X=0, Y=R 2 f (x, y) x 2 y R 2 0 Luego probamos las siguientes condiciones para averiguar si el punto se encuentra sobre la curva propuesta o sobre las hipotéticas interior y exterior. f (x, y) 0 circunferencia interna f (x, y) 0 circunferencia propuesta f (x, y) 0 circunferencia exterior Además debemos probar si el siguiente punto de la iteración, corresponde a alguna de las curvas que difieren por sólo ½ píxel en la ordenada, que para efectos prácticos viene siendo aproximadamente de la magnitud del radio. Ahora incorporamos estas ideas a la función de la circunferencia y en su momento a la de la elipse. Primeramente determinamos la función de la circunferencia para el siguiente punto, que difiere sólo ½ píxel en la oordenada…que al principio del método coincide con el radio R. Gráficas e imágenes con Java 1 2 f (x 1, y ) (x1) ( y 2 1 2 2 ) R 2 1 pn f (xn 1, yn ) 2 1 pn1 f (xn1 1, y n1 ) 2 1.- Ahora consideramos que Po se determina a partir de Xi=0; y Yi=R: 1 p f (0 1, R ) 0 2 1 1 p0 1 2(R)( ) 2 4 5 p R 0 4 Por lo que básicamente la primara “P” es para fines prácticos igual a 1-R: 2.- Mientras P es menor que cero. pn 0 xn1 xn 1 yn1 yn pn1 pn 2(xn1 ) 1 3.- Otro caso si P mayor que cero: p 0 n xn1 xn 1 yn1 yn 1 pn1 pn 2(xn1 ) 2( yn1 ) 1 4.- Repetir 2 o 3 hasta que completamos el sector 1 es decir; dy dx Y finalmente por simetría completamos los demás sectores. 1 Gráficas e imágenes con Java Ahora veamos la adaptación de todo lo anterior al caso mas general de la elipse: f (x, y) b2 x2 a2 y2 a2b2 0 En el caso de la elipse la frontera de las secciones 1 y 2 se define de manera similar a la de la circunferencia: dy 1 dx dy 2b2 x 2 dx 2a y Partimos del punto X=0, Y=b; entonces el primer parámetro en el sector 1. 1.- Se calcula la primera “P” del primer sector 1 p01 b2 a2b ( )a2 4 2.- Para el caso de P<0 pn1 0 xn1 xn 1 yn1 yn pn11 pn1 2b2 (xn1 ) b 2 Gráficas e imágenes con Java 3.- Otro caso P>0 pn1> 0 x n+1 =x n +1 yn+1= yn−1 pn+1= pn+2b2 ( xn+1 )−2a2( y n+1 )+b2 4.- Repetir 2 o 3 hasta que se completa el primer sector, que tiene condiciones de frontera Siguientes: dy 1 dx dy 2b2 x 2 dx 2a y º 5.- Calcular “P” para el sector 2. p02 b2 (xf 0.5)2 a2 ( yf 1)2 a2b2 Donde xf e yf son las últimas coordenadas calculadas en el sector 1. 6.- Si P > 0 entonces: pn2 0 xn1 xn yn1 yn 1 pn21 pn 2 2a 2 y n1 a 2 7.- Otro caso si P < 0: pn 2 0 xn1 xn 1 yn1 yn 1 p n 21 p n 2 2b2 x n1 2a 2 y n1 a 2 8.- Repetir 6 o 7 hasta que Xn= a; Yn=0; es decir hasta el final del sector 2. Posteriormente completamos el resto de la elipse por el principio de simetría al igual que con la circunferencia. A continuación codigo de JAVA con la solución: package bresh.prim; public class Bres_Oval { Gráficas e imágenes con Java private int xc,xr,yc,yr; private int p; public Bres_Oval(){xc=0;yc=0; xr=10;yr=10;} public Bres_Oval(int xc, int yc, int r){ this.xc=xc;this.yc=yc;xr=r;yr=xr;} public Bres_Oval(int r){ xc=0;yc=0; xr=r;yr=xr;} public Bres_Oval(int ra, int rb){ xc=0;yc=0; xr=ra;yr=rb;} public Bres_Oval(int xc, int yc, int ra, int rb) { this.xc=xc;this.yc=yc; xr=ra;yr=rb; } public void calcOval(){ if(xr==yr)circ(); else elipse(); } private void circ(){ int x, y; x=0; y=yr; System.out.println("x := "+(x+xc)+ " y := "+(y+yc)); p=1-xr; x++; while(x<=y){ if(p<0){ System.out.println("x := "+(x+xc)+ " y := "+(y+yc)); p=p+(2*x) +1; }else { y=y-1; System.out.println("x := "+(x+xc)+ " y := "+(y+yc)); p=p+(2*x)-(2*y)+1; } x++; } } private void elipse(){ int x, y; x=0; y=yr; System.out.println("x := "+(x+xc)+ " y := "+(y+yc)); p=(yr*yr) -(xr*xr*yr) +((xr*xr)>>2); Gráficas e imágenes con Java x++; try{ while((2*x*(yr*yr))<(2*y*(xr*xr))){ if(p<0){ System.out.println("x := "+(x+xc)+ " y := "+(y+yc)); p=p+ (2*x*(yr*yr)) + (yr*yr); } else{ y=y-1; System.out.println("x := "+(x+xc)+ " y := "+(y+yc)); p=p+ (2*x*(yr*yr)) + (yr*yr)- (2*y*(xr*xr)); } x++; Thread.sleep(500); } }catch(InterruptedException xe){xe.printStackTrace();} System.out.println("fin reghion 1 ..x := "+(x+xc)+ " y := "+(y+yc)); p=(int)Math.round((yr*yr)*(x+0.5)*(x+0.5)+(xr*xr)*(y-1)*(y-1)-(xr*xr)*(yr*yr)); try{ while(y>0){ if(p>0){ y=y-1;System.out.println("x := "+(x+xc)+ " y := "+(y+yc)); p=p-(2*y*(xr*xr))+(xr*xr); } else{ x=x+1;y=y-1; System.out.println("x := "+(x+xc)+ " y := "+(y+yc)); p=p-(2*y*(xr*xr))+(xr*xr)+(2*x*(yr*yr)); } Thread.sleep(500); } }catch(InterruptedException xe){xe.printStackTrace();} } } Por supuesto que este tipo de código es sólo para poner de ejemplo el cálculo sencillo de los sectores de la circunferencia/elipse. La verdad es que la API 2D de Java tiene soluciones muchisimo más poderosas y versátiles; simplemente considere las implementaciones de JRE´s para OpenGL y DirectX. La parábola tiene una importancia especial en Ingeniería, por ello vamos a ver el método DDA para la parábola, el cual es rapidísimo, aunque lamentablemente requiere de redondeo , para algunas aplicaciones de simulación puede ser suficiente la aproximación con diferencias digitales. y ax 2 2 y x a(xx) Gráficas e imágenes con Java y y a( x 2xx x ) y x a(2x x) 2 2 Si: y 1 x xn1 x 1 y yn1 y x Por otra parte si: y 1 x x x n1 y x y y 1 n1 Se puede implementar el método del medio punto para la parábola considerando en primer lugar la ecuación más sencilla de dicha curva cónica, para el caso, con el eje paralelo a “Y”. y ax 2 Donde: 1 a 4p Siendo “P” la posición del foco de la parábola respecto al vértice de la misma. Lo decisión sobre que pixel activar se basa en el valor de la derivada dy/dx=2ax. Sólo en la región cercana al vértice la derivada es pequeña y esta depende de la magnitud de P. Algunos elementos de Java 2D que lo hacen muy atractivo para implementar soluciones gráficas en sistemas completos pero igualmente en sistemas empotrados en electrónica móvil y casera es la amplia cobertura de su API en capacidades gráficas. Algunos puntos importantes son: Modelado uniforme para desplegados gráficos Amplia cartera de primitivas gráficas, incluidas curvas de interpolación polinomial. Detección de traslapes con figuras, texto e imágenes. Gráficas e imágenes con Java Soporte para diversos modelos de color. Impresión de documentos. Tipos sugeridos de despliegue. En la siguiente figura se muestra la salida de una pequeña aplicación con Java 2D, en la cual se simula una ventana a un paisaje. Las montañas y la nieve se hicieron con una serie de polígonos concatenados, mientras que la Luna, con la simple elipse. Una de las grandes ventajas de desplegar gráficos con la API 2D es que se presenta la independencia de dispositivo de salida…así pues desde el punto de vista del rendimiento de las primitivas gráficas, da lo mismo la salida a una pantalla LCD que a una impresora. Esto es la independencia de dispositivo. Primitivas geométricas en Java 2D La API 2D de Java proporciona un conjunto de elementos basicos en gráficas 2D (primitivas), tales como puntos, líneas, rectángulos, polígonos, elipses, curvas de interpolación y figuras en general. El paquete de clases sin duda más importante para los propósitos de graficar objetos 2D es java.awt.geom. En la programación de graficas 2D con Java la interfaz “Shape” representa en general una figura geométrica cualquiera, que tiene perímetro y una superficie interior. Tal interfaz proporciona una serie de métodos adaptados para describir y ejecutar objetos de dos dimensiones. Antes de continuar con nuestro primer ejemplo de Graphics2D remarcamos que la clase Graphics soporta segmentos de figuras con lineas rectas, Gráficas e imágenes con Java mientras que la interfaz Shape permite segmentación de figuras con curvas de interpolación. La API 2D de Java es algo complicada de digerir en principio, pero es muy poderosa y te permite implementar soluciones creativas en poco tiempo. No obstante comenzamos con un subconjunto de sencillos metodos gráficos para objetos 2D, que localizamos en la clase calificada java.awt.Graphics. Básicamente los métodos de la clase Graphics pueden estudiarse por sus efectos. Metodos de dibujo e iluminación, para figuras primitivas, texto e imágenes. Metodos de ajuste de atributos de dibujo e iluminación. En Java todo es Object y los objetos gráficos 2D e inclusive los de 3D también son Object. Sin embargo son objetos de una jerarquía especial para contener gráficos, esto es los componentes gráficos del sistema de ventanas de Java se organizan básicamente de la siguiente manera. Ahora para completar la idea de nuestro primer ejercicio con Java 2D, tenemos que recordar que el sistema operativo que envuelve a la aplicación, en este caso una aplicación de java, es multitarea y reacciona a diversos eventos, la mayoría de ellos de naturaleza asíncrona, por lo que debemos de dotar a nuestro ejercicio con la capacidad de responder a eventos. En Java la reacción a los eventos que transitan por el sistema operativo de hospedaje, se delega a los componentes responsables de procesar o al menos enlutar, el o los eventos asociados a tales componentes. Gráficas e imágenes con Java Algunos eventos son desencadenados por el usuario de nuestra aplicación, pero otros eventos son temporizados por el propio sistema operativo, por ejemplo, cada tanto tiempo se tiene que refrescar el contenido de la memoria de video, se puede aprovechar ese hecho para actualizar el contenido gráfico de algún componente, por ejemplo, el contenido de un Applet, o de un Lienzo(Canvas). Nuestro primer ejercicio en Java 2D consta de un par de componentes, un marco que a su vez contiene un applet en cuya superficie se despliega el contexto gráfico, independiente del dispositivo; es en ese contexto en el que dibujamos la cadena “hola mundo”. Para cerrar la idea, este ejercicio procesará dos mensajes: 1. Actualizar el área del applet. 2. Cerrar la aplicación y terminar el applet. A continuación nuestro primer ejercicio: //aplicacion de java con una ventana para mostrar el applet // hola mundo @seic 2008 udg Gráficas e imágenes con Java import java.awt.*; import java.awt.event.*; import java.applet.*; class cierraVentana extends WindowAdapter { public void windowClosing(WindowEvent e){System.exit(0);} } public class CA_Hola1 extends Applet { public CA_Hola1() {System.out.println("estoy en el constructor");} public void init() { resize(300,300); System.out.println("estoy en el init"); } public void start() { System.out.println("estoy en el start");} public void paint(Graphics g) { g.drawString("Hola mundo con applet ", 50, 50); } public void stop(){System.out.println("estoy en el stop");} public void destroy(){System.out.println("estoy en el destructor");} public static void main(String arg[]) { CA_Hola1 cosa=new CA_Hola1(); Frame marco=new Frame("Mi Ventana"); marco.addWindowListener(new cierraVentana()); marco.setSize(320,320); cosa.init(); cosa.start(); Gráficas e imágenes con Java marco.add("Center",cosa); marco.setVisible(true); } } Aplicaciones gráficas con SWING. Veamos las clases principales de SWING. A continuación un código de ejemplo con SWING. import com.sun.java.swing.*; public class JHolaMundo extends JFrame { public static void main( String argv[] ) { new JHolaMundo(); } JHolaMundo() { JLabel hola = new JLabel( "Hola Mundo!" ); getContentPane().add( hola,"Center" ); setSize( 200,100); setVisible( true ); } }