Sie sind auf Seite 1von 36

Buenas tardes este es el cdigo que he creado para obtener un visor de imgenes: import import import import import

java.awt.Dimension; java.awt.Graphics; java.awt.Image; java.awt.Toolkit; java.io.File;

import javax.swing.JPanel;

public class PanelImage extends JPanel{ private Image imagen; public PanelImage(Image imagen,int ancho, int alto ){ this.imagen=imagen; this.setSize(new Dimension (ancho, alto)); }//constructor public Image getImagen(){ return imagen; }//nos permite consultar imagenes public void setImagen(Image imagen){ this.imagen=imagen; this.repaint(); }//cambia imagen public void setIMagenFromFile(File file){ this.imagen=Toolkit.getDefaultToolkit().getImage(file.getAbsolutePath()); this.repaint(); }//

public void paintComponent(Graphics g){ super.paintComponent(g); g.drawImage(this.getImagen(),0,0,this.getWidth(),this.getHeight(),this); }// }//class

import import import import import

java.awt.*; java.awt.event.*; javax.swing.*; javax.swing.event.*; java.util.*;

//Frames. //SplitPaneDemo itself is not a visible component. public class SplitPaneDemo implements ListSelectionListener { //Visor de imagenes. private Vector imageNames; private JLabel picture; //la imagen q se mostrara. private JList list; //la lista de eleccion de imagenes. private JSplitPane splitPane; //Divide la ventana.

public SplitPaneDemo() { //Constructor. //Leer los nombres de imgenes desde un archivo de propiedades. ResourceBundle imageResource; try {imageResource = ResourceBundle.getBundle("imagenames" ; //Indicamos el archivo imagenames.properties --> images=, es decir una variable que contiene parametros o valores. String imageNamesString = imageResource.getString("images" ;//Indicamos el parametro de referencia de los datos a recoger. Recoge los nombres de images=, es decir: "...jpg ...jpg ...jpg" imageNames = parseList(imageNamesString);} //Guardamos en el Vector los valores del vector 'v' de el metodo --> protected static Vector parseList(String theStringList). (que se encuentra mas abajo, en el programa). catch (MissingResourceException e) {System.out.println("No se puede encontrar el archivo de propiedades que contiene los nombres de las imgenes" ;}

//Crear la lista de imgenes y ponerla en un ScrollPane. list = new JList(imageNames); //Inicializamos la lista pasandole los nombres de las imagenes contenidas en el vector imageNames (Ya separadas). list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); //Establecer el mode de seleccion, tipo simple, solo una opcion seleccionada.

list.setSelectedIndex(0); //Por defecto aparecera seleccionado el primer elemento de la lista. list.addListSelectionListener(this); //Creamos un oyente para la lista. JScrollPane listScrollPane = new JScrollPane(list); //Metemos la lista en un JScrollPane (Panel con barras de desplazamiento). //Configura la picture label y la coloca en el ScrollPane ImageIcon firstImage = new ImageIcon("images/" +(String)imageNames.firstElement());//Creamos una imagen, y le decimos que su valor inicial sea el nombre del primer elemento del vector convertido a string. Esto es para decirle que la primera imagen esta en la carpeta images/nombredelprimerelemento, es decir --> images/francia.jpg. picture = new JLabel(firstImage); //Inicializamos la etiqueta con esa imagen. picture.setPreferredSize(new Dimension(firstImage.getIconWidth(),firstImage.getIconHeight())); //Ponemos un tamao a la etiqueta. La etiqueta tiene el tamao de la imagen que contendra. JScrollPane pictureScrollPane = new JScrollPane(picture); //Metemos en un JScrollPane la imagen. //Crear un SplitPane con dos ScrollPane en l. splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);//Divimos la ventana en horizontal (Una linea vertical). splitPane.setLeftComponent(listScrollPane); //En el lado izquierdo pon lo el listScrollPane. splitPane.setRightComponent(pictureScrollPane); //En el lado derecho pon lo el pictureScrollPane. splitPane.setOneTouchExpandable(true); //Aade la opcion de expandir. //Configurar el tamao mnimo para los dos componentes en el SplitPane. Dimension minimumSize = new Dimension(100, 50); //Define el tamao minimo. listScrollPane.setMinimumSize(minimumSize); //Tamao minimo de el listScrollPane. pictureScrollPane.setMinimumSize(minimumSize); //Tamao minimo de el pictureScrollPane. //Establecer la localizacin y el tamao iniciales del divisor. splitPane.setDividerLocation(150); //La barra de division se encontrara en la posicion... --> 150. splitPane.setDividerSize(10); //La barra de division tendra un grosor de... --> 10.

//Configurar el tamao preferido para el SplitPane. splitPane.setPreferredSize(new Dimension(400, 200)); }//Fin-Constructor. public JSplitPane getSplitPane() {return splitPane;} //Metodo que devuelve el valor del splitPane. public void valueChanged(ListSelectionEvent e) {//Metodo que va ha ser llamado cada vez que ocurra un cambio en la lista. if (e.getValueIsAdjusting()) //Devuelve 'true' si ha ocurrido multiples eventos (se ha seleccionado varios elementos). return; //Sale del metodo. Devuelve el control del programa al main (que es quien lo llamo). JList theList=(JList)e.getSource(); //Creamos un objeto JList donde le pasamos el valor e.getSource(), que significa obtener la fuente, y la convierte a tipo JList. if (theList.isSelectionEmpty()) //Si theList tiene una seleccion vacia. picture.setIcon(null); //No pongas ninguna imagen. else{ int index=theList.getSelectedIndex(); //Le pasamos el indice seleccionado de la lista. ImageIcon newImage = new ImageIcon("images/"+(String)imageNames.elementAt(index)); //Le indicamos la imagen que queremos que se muestre. picture.setIcon(newImage); //Enviamos la imagen que se encuentra en newImage. picture.setPreferredSize(new Dimension(newImage.getIconWidth(),newImage.getIconHeight() )); //Preferencia de tamao de imagen. picture.revalidate(); //Refresca la etiqueta. } }//Fin-valueChanged. protected static Vector parseList(String theStringList) { //Le pasamos la cadena sin separar. --> "francia.jpg espana.jpg italia.jpg alemania.jpg" Vector v = new Vector(10); //Creamos un vector con 10 posiciones. StringTokenizer tokenizer = new StringTokenizer(theStringList, " " ;//la cadena que keremos separar y el " " (espacio) que es lo que actua como separador.

while (tokenizer.hasMoreTokens()){ //Divide las cadenas y los aade a el vector 'v'. String image = tokenizer.nextToken(); v.addElement(image);} return v; //Devuelve 'v'. Esto es lo que dara el valor al otro vector, imageNames. }//fin-parseList. //Crea la ventana y muestra el contenido. public static void main(String s[]) { JFrame frame=new JFrame("SplitPaneDemo" ; //Creamos una Frame, pasandole como valor un nombre que aparecera en la barra de titulo. frame.addWindowListener(new WindowAdapter(){ //Aadimos un oyente para el frame. public void windowClosing(WindowEvent e)//Evento para cuando se cierre la ventana. {System.exit(0);}}); SplitPaneDemo splitPaneDemo=new SplitPaneDemo(); //Creamos un objeto de la clase SplitPaneDemo (La cual creamos en este programa). frame.getContentPane().add(splitPaneDemo.getSplitPane()); //Obtener el contenedor de la ventana. --> Container contenedor=frame.getContentPane(); //Aadir al contenedor --> contenedor.add(splitPaneDemo.getSplitPane()); //splitPaneDemo.getSplitPane() porque no podemos llamar a splitPane directamente, //ya que el main es estatico y en ningun sentido podriamos conseguirlo, //por lo que creamos un objeto de la clase SplitPaneDemo y asi podremos utilizar //el metodo getSplitPane() que devuelve el valor del splitPane. frame.pack(); //Dimensiona la ventana para que se ajuste a su contenido. frame.setVisible(true); //Hacer visible el frame. }//Fin-main. }//Fin.

La clase Graphics, Mtodos para Imgenes


Anterior | Siguiente

Mtodos de Clipping
La palabra Clipping est muy arraigada entre los programadores grficos, sin tener una contrapartida en espaol adecuada, ya que quiz la que ms se asemeje sea recorte, pero tampoco es demasiado precisa; por ello, el autor va a seguir utilizando el trmino sajn, an a pesar de la reticencia de los puristas del espaol. Clipping es el proceso por el que se define la zona del contexto grfico en la que se van a realizar las modificaciones de los subsiguientes procesos de dibujo. Cualquier pixel que se encuentre fuera del rea de clipping permanecer inmune a toda modificacin. Los mtodos que estn involucrados son varios, unos que permiten fijar el rectngulo de clipping y otros que permiten obtener la zona de clipping actual. clipRect( int,int,int,int ), realiza la interseccin del rectngulo de clipping actual con el formado por los parmetros que se pasan al mtodo. Este mtodo solamente se puede utilizar para reducir el tamao de la zona de clipping, no para aumentarla. getClip(), devuelve la zona de clipping actual como un objeto de tipo Shape. No obstante, Shapees un interface, por lo que hay que tener cuidado en su uso, y adems consultar la documentacin delAPI Java2D, en donde ha sido completamente revisada, as que lo mejor es evitar el uso de este interfaz en el cdigo propio. getClipBounds(), devuelve el rectngulo que delimita el borde de la zona de clipping actual. setClip (int,int,int,int ), fija el rectngulo de clipping actual al indicado en las cuatro coordenadas que se pasan como parmetro al mtodo.

Mtodos para manejo de Imgenes


Hay varias formas distintas para el mtodo drawImage(), que difieren fundamentalmente en las posibilidades de manipulacin del mtodo y los parmetros que hay que pasar para realizar esas manipulaciones. La siguiente llamada es solamente representativa del grupo, que se vern posteriormente. drawImage( Image,int,int,int,int,int,int,int,int,Color,ImageObserver ), pinta sobre la zona indicada la imagen que se pasa como parmetro, escalndola sobre la marcha para que rellene completamente el rea de destino. No obstante, antes de entrar en el desarrollo de los diferentes mtodos drawImage(), quiz sea presentar la clase Color, que es relativamente simple de entender y utilizar.

La clase Color
Esta clase es simple, encapsula los colores utilizando el formato RGB. En este formato, los colores se definen por sus componentes Rojo, Verde y Azul, representado cada uno de ellos por un nmero entero en el rango 0-255. En el caso del API Java2D, el espacio de color que se usa es el sRGB, un

estndar del consorcio W3. Hay otro modelo de color llamado HSB (matiz, saturacin y brillo). La clase Color proporciona mtodos de conveniencia para poder realizar la conversin entre un modelo y otro sin dificultad. La clase Color proporciona variables estticas finales que permiten el uso de cualquiera de los treinta colores, simplemente especificando su nombre. Para usar estas variables slo es necesario referencias el color por su nombre de variable, por ejemplo objeto.setBackground( Color.red ); Los valores predefinidos para los colores en esta clase son los que se muestran en la siguiente lista, todos ellos en el espacio sRGB: black, negro blue, azul cyan, azul celeste darkGray, gris oscuro gray, gris green, verde lightGray, gris claro magenta, violeta orange, naranja pink, rosa red, rojo white, blanco yellow, amarillo

Los constructores de esta clase son tres, dos de los cuales permiten instanciar un nuevo objeto de tipo Color indicando las cantidades de rojo, verde y azul que entran en su composicin mediante valores enteros en el rango 0 a 255: Color( int,int,int ) El otro de los constructores que permite especificar la contribucin de rojo, verde y azul al color final, admite valore flotantes en el rango 0.0 a 1.0: Color( float,float,float ) Y el tercer constructor admite solamente un nmero entero en el cual se especifica el valor RGB, de forma que la cantidad de color rojo que interviene en el color final est especificada en los bits 16-23 del argumento, la cantidad de verde en los bits 8-15 y la cantidad de azul en los bits 0-7. Color( int ) Para el uso con los colores, JDK dispone de una serie de mtodos, de los cuales JavaSoft proporciona una completa descripcin en la documentacin del AWT. Aqu se intentan englobar en base a su funcionalidad. Mtodos que devuelven un entero representando el valor RGB para un determinado objeto Color.

getRed(), devuelve el componente rojo del color como un entero en el rango 0 a 255. getGreen(), devuelve la cantidad de verde que entra en la composicin del objeto Color, en el rango 0 a 255. getBlue(), devuelve el componente azul del color con un entero en el rango 0 a 255. getRGB(), devuelve un entero representando el color RGB, utilizando los bits para indicar la cantidad de cada uno de los componentes rojo, verde y azul que entran en su composicin. Los bits 24 a 31 del entero que devuelve el mtodo son 0xff, los bits 16 a 23 son el valor rojo, los bits 8 a 15 son el valor verde y los bits 0 a 7 indican el valor del color azul. Siempre en el rango 0 a 255. Los siguiente mtodos devuelven un objeto de tipo Color, de forma que se pueden utilizar para crear objetos de este tipo. brighter(), crea una versin ms brillante del color. darker(), crea una versin ms oscura del color. decode( String ), convierte una cadena a un entero y devuelve el color correspondiente. Los mtodos que se indican a continuacin, tambin devuelven un objeto de tipo Color, pero estn especializados para trabajar con el sistema a travs de la clase Properties. getColor( String ), busca un color entre las propiedades del sistema. El objeto String se utiliza como el valor clave en el esquema clave/valor utilizado para describir las propiedades en Java. El valor es entonces utilizado para devolver un objeto Color. getColor( String,Color ), busca un color entre las propiedades del sistema. El segundo parmetro es el que se devuelve en el caso de que falle la bsqueda de la clave indicada en el objeto String. getColor( String,int ), busca un color entre las propiedades del sistema. El segundo parmetro es utilizado para instanciar y devolver un objeto Color en el caso de que falle la bsqueda de la clave indicada en el objeto String. Los siguientes mtodos se utilizan para realizar la conversin entre el modelo de color RGB y el modeloHSB. getHSBColor( float,float,float ), crea un objeto de tipo Color basado en los valores proporcionados por el modelo HSB. HSBtoRGB( float,float,float ), convierte los componentes de un color, tal como se especifican en el modelo HSB, a su conjunto equivalente de valores en el modelo RGB. RGBtoHSB( int,int,int,float[] ), convierte los componentes de un color, tal como se especifican en el modelo RGB, a los tres componentes del modelo HSB. Y ya, los mtodos que quedan son mtodos de utilidad general, sin ninguna aplicacin especfica en

lo que al Color respecta. equals( Object ), determina si otro objeto es igual a un color. hashCode(), calcula el cdigo hash para un color. toString(), crea una cadena representando al color, indicando el valor de sus componentes RGB.

El mtodo drawImage()
Este mtodo es el que se utiliza para presentar una imagen en pantalla; aunque hay mtodos de otras clases que son utilizados para la manipulacin de imgenes en Java, lo primero que se necesita es saber cmo se visualiza una imagen, y eso es lo que hace este mtodo drawImage() de la claseGraphics. Hay varias versiones sobrecargadas de este mtodo, algunas de las cuales se muestran a continuacin, aunque el lector debe referirse a la documentacin del API de Java para disponer de informacin detallada de cada uno de estas formas. drawImage( Image,int,int,Color,ImageObserver ), pinta la imagen que se indica situando su esquina superior izquierda en la coordenada que se pasa, en el contexto grfico actual. Los pixeles transparentes se pintan en el color de fondo que se indica. Esta operacin es equivalente a rellenar un rectngulo del ancho y alto de la imagen dada con un color y luego pintar la imagen sobre l, aunque probablemente ms eficiente. drawImage( Image,int,int,ImageObserver ), pinta la imagen que se indica situando su esquina superior izquierda en la coordenada que se pasa, en el contexto grfico actual. Los pixeles transparentes de la imagen no se ven afectados. Este mtodo retorna inmediatamente en todos los casos, incluso aunque la imagen completa no se haya terminado de cargar y no se haya presentado completamente en el dispositivo de salida. drawImage( Image,int,int,int,int,Color,ImageObserver ), pinta la imagen que se pasa dentro del rectngulo que se indica en los parmetros, escalando esa imagen si es necesario. El mtodo retorna inmediatamente, aunque la imagen no se haya cargado completamente. Si la representacin de la imagen en el dispositivo de salida no se ha completado, entonces drawImage() devuelve el valor false. drawImage( Image,int,int,int,int,ImageObserver ), pinta la imagen que se pasa dentro del rectngulo que se indica en los parmetros, escalando esa imagen si es necesario. El mtodo retorna inmediatamente, aunque la imagen no se haya cargado completamente. Si la representacin de la imagen en el dispositivo de salida no se ha completado, entonces drawImage() devuelve el valor false. El proceso que pinta las imgenes notifica al observador a travs de su mtodo imageUpdate(). drawImage( Image,int,int,int,int,int,int,int,int,Color,ImageObserver ). drawImage( Image,int,int,int,int,int,int,int,int,ImageObserver ). Como puede comprobar el lector, se permite mucha flexibilidad a la hora de presentar imgenes, aunque quiz necesite una descripcin ms detallada de la llamada a cada mtodo, por ejemplo, la

descripcin que encontrar en el API para una de las versiones del mtodo es: public abstract boolean drawImage( Image img, int x, int y, int width, int height, ImageObserver observer ) Los parmetros del mtodo son: img, la imagen que se quiere pintar x e y, coordenadas para posicionar la esquina superior izquierda de la imagen width y height, dimensiones del rectngulo sobre el que se posicionar la imagen observer, objeto que ha de ser notificado tan pronto como la imagen se haya convertido y situado en su posicin En esta versin del mtodo, la imagen se pintar dentro del rectngulo que se para en los parmetros y se escalar si es necesario. El mtodo retorna inmediatamente, incluso aunque la imagen no se haya terminado de escalar o convertir al formato que admita el dispositivo de salida. Si esta conversin no se ha completado, drawImage() devuelve false, y como hay parte de imagen que no est procesada, el proceso que pinta la imagen notifica al observador a travs de su mtodo imageUpdate() y esa imagen contina pintndose por trozos. El mtodo imageUpdate() pertenece a la clase Component, cuando es llamado, encola una llamada arepaint(), permitiendo que se pinta un trozo ms de imagen sin que se interfiera la tarea o hilo de control principal. Hay tambin una propiedad, awt.image.incrementaldraw que determina si la imagen puede ser pintada en piezas, tal como se ha indicado antes. El valor por defecto para esta propiedad es true, en cuyo caso el sistema va pintado trozos de imagen segn van llegando. Si el valor es false, el sistema esperar a que la imagen est completamente cargada antes de pintarla. Hay una segunda propiedad, awt.image.redrawrate que determina el perodo mnimo, en milisegundos, que debe haber entre llamadas a repaint() para imgenes. El valor por defecto es 100, y solamente se aplica cuando la propiedad anterior es true. Tanto esta propiedad como la anterior se pueden modificar, pero solamente sirve esa modificacin para la ejecucin actual del programa. En el ejemplo java1518.java se muestra el efecto de pintar una imagen en trozos, segn van estando disponibles, adems del escalado de esa imagen. La salida visual que se genera no es demasiado satisfactoria porque tiende a producir un cierto parpadeo al realizar varias llamadas al mtodoimageUpdate() durante el proceso de pintado de la imagen. No obstante, esto se corregir en el ejemplo siguiente, java1519.java, con el uso de un objeto de tipo MediaTacker. Segn la documentacin de JavaSoft, la versin escalada de una imagen no necesariamente estar disponible inmediatamente, porque antes debe construirse una versin en dimensiones normales para el dispositivo de salida, sin embargo, como podr comprobar el lector en el ejemplo java1519.java, este efecto aparentemente no se produce. De los parmetros que se pasan al mtodo drawImage(), todos resultan obvios, excepto quiz, el ltimo de ellos, observer, que se refiere al objeto que debe ser notificado cuando la imagen est disponible. Cuando se realiza una llamada a drawImage(), se lanza una tarea que carga la imagen solicitada. Hay un observador que monitoriza el proceso de carga; la tarea que est cargando la

imagen notifica a ese observador cada vez que llegan nuevos datos. Para este parmetro se puede utilizar perfectamente this como observador en la llamada a drawImage(); es ms, se puede decir que cualquier componente puede servir como observador para imgenes que se pintan sobre l. Quiz sea este el momento de entrar un poco ms en detalle en la clase ImageObserver, e incluso antes en la clase Image, porque son los dos parmetros diferentes del tpico entero que aparecen en la llamada adrawImage().

La clase Image
La clase Image, como cualquier otra, est formada por una serie de constantes o variables, constructores y mtodos. Uno de estos mtodos es getScaledInstance(), que devuelve una versin escalada de una imagen. Uno de los parmetros de este mtodo es un valor entero que especifica el algoritmo a utilizar para la realizacin del escalado. Se puede utilizar cualquiera de ellos, la tabla siguiente muestra su nombre y una pequea descripcin, si el lector necesita ms detalles, debe recurrir como siempre se recomienda, a la documentacin del JDK. SCALE_AREA_AVERAGING, utiliza el algoritmo Area Averaging SCALE_FAST, utiliza un algoritmo que proporcione mayor rapidez en el escalado, a costa de la suavidad de realizacin de ese escalado SCALE_SMOOTH, al contrario que el anterior, sacrifica la velocidad por la suavidad de realizacin del escalado SCALE_REPLICATE, utiliza un algoritmo de los internos de la clase ReplicateScaleFilter SCALE_DEFAULT, utiliza el algoritmo de defecto UndefinedProperty, un objeto de este tipo debe ser retornado siempre que una propiedad no se encuentre definida para una determinada imagen. Esta propiedad no se utiliza para el escalado, sino que es utilizada como valor de retorno del mtodo getProperties() para indicar que la propiedad solicitada no est disponible. Aunque la clase Image dispone de un constructor, es una clase abstracta, por lo que no se puede instanciar ningn objeto llamando directamente a este constructor. Se puede conseguir un objetoImage indirectamente por la invocacin del mtodo getImage() de las clases Applet o Toolkit. El mtodo getImage() utiliza un hilo de ejecucin, o tarea, separado para cargar la imagen. El resultado prctico de la invocacin a getImage(), es la asociacin entre una referencia de tipo Image y un fichero localizado en algn lugar que contiene la imagen que interesa; en este Tutorial se utilizan imgenes que estn en el disco local, pero no se impide que puedan encontrarse en cualquier servidor de la Red. Otra forma de obtener un objeto Image es invocar al mtodo createImage(), de las clasesComponent y Toolkit. La lista siguiente muestra una pequea descripcin de los mtodos de la claseImage; la documentacin de JavaSoft puede proporcionar al lector una descripcin ms completa. flush(), libera todos los recursos que utiliza el objeto Image getGraphics(), crea un contexto grfico para pintar una imagen en segundo plano getHeight( ImageObserver ), determina la altura de la imagen getWidth( ImageObserver ), determina la anchura de la imagen

getProperty( String,ImageObserver ), obtiene una propiedad de la imagen por su nombre getScaledInstance( int,int,int ), crea una versin escalada de la imagen getSource(), devuelve el objeto que produce los pixeles de la imagen Algunos de estos mtodos se utilizarn en los ejemplos que se presentan. No obstante, el inters no debe centrarse solamente en la clase Image, sino tambin en las otras clases que se necesitan para instanciar los parmetros de llamada a estos mtodos, e incluso, algunas otras clases de soporte general. Por ello, an a costa de resultar un poco ladrillo, se presenta a continuacin una pequea revisin de las clases ms interesantes, MediaTracker e ImageProducer, ya que sobre las clasesString, ImageObserver, Graphics y Object, que son las que intervienen en los mtodos de la clase Image, ya debera tener el lector alguna referencia; no obstante, si desea ampliar detalles sobre cualquiera de las clases e interfaces que dan soporte a los mtodos de la clase Image, siempre queda el recurso de otros libros, tutoriales y, pro supuesto, la documentacin de JavaSoft.

El interfaz ImageProducer
Se trata de un interfaz para objeto que pueden producir imgenes para la clase Image. Cada imagen contiene un ImageProducer que se utiliza en la reconstruccin de esa imagen cuando es necesario; por ejemplo, cuando se escala la imagen, o cuando se cambia la imagen de tamao. Este interfaz declara varios mtodos, algunos de los cuales se vern un poco ms adelante.

La clase MediaTracker
Esta es una clase de utilidad general diseada para controlar el estado de los objetos de tipo media, que en teora pueden ser tanto clips de sonido como cualquier otro objeto media, como es el caso de una imagen. Por ahora, en el JDK 1.2 solamente se soporta el control de imgenes. Un objeto MediaTracker se utiliza a travs de una instancia de la clase MediaTracker sobre el objeto Component que se quiere monitorizar, e invocando al mtodo addImage() para cada una de las imgenes que se quiere controlar. A cada una de estas imgenes se puede asignar un identificador nico, o tambin se puede asignar el mismo identificador a un grupo de imgenes. Este identificador controla el orden de prioridad en que se cargarn las imgenes, de forma que imgenes con un identificador bajo tienen preferencia sobre otras con identificador ms alto. El identificador tambin se puede utilizar para identificar un conjunto nico de imgenes. En otras palabras, asignando el mismo identificador a varias imgenes, se las puede manejar a la vez. Se puede determinar el estado de una imagen (o grupo de imgenes) invocando alguno de los distintos mtodos sobre el objeto MediaTracker, pasndole como parmetro el identificador de la imagen (o grupo de imgenes). El objeto MediaTracker tambin se puede utilizar para bloquear la ejecucin a la espera de la carga completa de una imagen (o grupo de imgenes), tal como se ver en alguno de los ejemplos, en que se espera a que la carga de las imgenes se realice completamente antes de presentarlas en pantalla. La clase MediaTracker proporciona cuatro constantes, que se utilizan como valores de retorno de algunos de los mtodos de la clase y, tal como su nombre sugiere, indican el estado en que se

encuentra una imagen dada. Estas constantes son las siguientes. ABORTED, la carga de la imagen (o cualquier media) ha sido abortada COMPLETE, realizara satisfactoriamente la carga completa ERRORED, se ha encontrado algn tipo de error en la carga LOADING, se est cargando la imagen (o cualquier media) Para esta clase solamente hay un constructor que pueda ser invocado a la hora de instanciar objetos que controlen el estado de algunas, o todas, las imgenes sobre un determinado componente. MediaTracker( Component ) Sin embargo, el nmero de mtodos disponibles para los distintos propsitos, s que es bastante extenso. Se ha intentado agruparlos en categoras, pero se recuerda al lector, que lo que aqu se expone es una pequea descripcin de cada uno de ellos para poder tener una visin global del funcionamiento, en este caso de la manipulacin de imgenes, y que sea sencilla de entender su funcin; pero si el lector va a utilizar estos mtodos en sus propios programas, debe consultar la documentacin del API del JDK que est utilizando, donde encontrar toda la informacin que JavaSoft proporciona para cada uno de estos mtodos. Un objeto MediaTracker tiene la posibilidad de controlar el estado de algunas, o todas, las imgenes que estn siendo cargadas para el objeto Component que se ha pasado como parmetro a la hora de instanciar ese objeto MediaTracker. Los mtodos siguientes se utilizan para crear y mantener esta lista de imgenes. Cuando se aade una imagen a la lista, hay que proporcionar un identificador numrico para esa imagen, que ser luego el que sea utilizado por otros mtodos para poder indicar el estado en que se encuentra una imagen determinada. addImage( Image,int ), incorpora una nueva imagen a la lista de imgenes que est siendo controlada por el objeto MediaTracker. addImage( Image,int,int,int ), incorpora una imagen escalada a la lista. removeImage( Image ), elimina la imagen indicada de la lista. removeImage( Image,int ), elimina la imagen que corresponde al identificador que se pasa como parmetro de la lista. removeImage( Image,int,int,int ), elimina la imagen que corresponde al ancho, alto e identificador, de la lista de imgenes. El objeto MediaTracker se puede utilizar para hacer que la tarea, o hilo de ejecucin, se bloquee hasta que una o ms imgenes de su lista haya completado su carga. Esto se consigue con los siguientes mtodos. waitForAll(), inicia la carga de todas la imgenes controladas por el objeto MediaTracker; devuelve void. waitForAll( long ), inicia la carga de todas la imgenes, devolviendo true si todas las imgenes se han cargado y false en cualquier otro caso.

waitForID( int ), inicia la carga de las imgenes que corresponden al identificador que se pasa; devuelve void. waitForID( int,long ), inicia la carga de las imgenes que corresponden al identificador que se pasa; devuelve true si todas las imgenes se han cargado y false en cualquier otro caso. Por supuesto, es posible utilizar mtodos que no bloquean la tarea que carga las imgenes para comprobar el estado de una o ms imgenes de la lista. Esto permite continuar haciendo el trabajo mientras las imgenes siguen cargndose. Estos mtodos devuelven true o false para indicar si la carga es completa. Observar el lector que hay dos versiones sobrecargadas de cada uno de los mtodos. La versin con el parmetro booleano comenzar la carga de cualquier imagen que no se est cargando, en caso de que ese parmetro booleano sea true. La otra versin no iniciar la carga de ninguna imagen. Esta interpretacin tambin es vlida para el parmetro booleano de otros mtodos de la clase que disponen de l. checkAll() y checkAll( boolean ), comprueban si todas las imgenes que estn siendo controladas por el objeto MediaTracker han finalizado la carga. checkID( int ) y checkID( int,boolean ), comprueban si todas las imgenes que corresponden al identificador especificado han concluido su carga. El hecho de que los mtodos anteriores indiquen que la carga de las imgenes ha sido completa, no garantiza que esa carga est libre de errores. Los siguiente mtodos se utilizan para determinar si se ha producido algn problema durante la carga de las imgenes. getErrorsAny(), devuelve una lista de todas las imgenes (o cualquier media) en los que se ha producido un error en la carga. getErrorsAny( int ), devuelve una lista de todas las imgenes correspondientes a un determinado identificador, en los que se ha producido un error en la carga. isErrorAny(), comprueba el estado de error de todas las imgenes. isErrorID( int ), comprueba el estado de error de todas las imgenes correspondientes a un determinado identificador. Los dos siguientes mtodos devuelven un valor entero formado por la operacin OR entre los valores de estado de todas las imgenes que se requieren; en el primero de todas las que controla el objetoMediaTracker, y en el segundo de las que corresponden al identificador que se especifica. statusAll( boolean ) statusID( int,boolean ) El ejemplo java1518.java, como se ha indicado en algn prrafo anterior, muestra la carga y pintado de una imagen sin utilizar la clase MediaTracker, que s se utilizar en el ejemplo java1519.java. El ejemplo, no obstante, muestra el uso de la clase Toolkit y el mtodo getImage(), para asociar un fichero de imagen que se encuentra en el disco duro local, con el nombre de una variable de referencia de tipo Image. Tambin muestra el uso del mtodo drawImage() para pintar la imagen cargado sobre un objeto Frame; el uso de getWidth() y getHeight() para determinar el tamao de la

imagen; el uso de translate() para eliminar el efecto de offset generado por los insets del objeto Frame; y algunos otros mtodos que ya deben ser archiconocidos para el lector. El cdigo completo del ejemplo es el que se reproduce a continuacin. import java.awt.*; import java.awt.event.*; // Clase de control del ejemplo class java1518 extends Frame { // Referencia a la imagen Image imagen; // Constructor de la clase public java1518() { this.setTitle( "Tutorial de Java, Grficos" ); this.setSize( 275,250 ); // Recogemos en la variable "imagen" el fichero de imagen que // se indica, y que se supone situado en el mismo directorio y // disco que la clase del ejemplo imagen = Toolkit.getDefaultToolkit().getImage( "muneco.gif" ); // Se hace visible el Frame, que en la pantalla da origen a // la ventana, aunque la primera imagen no es visible en el // mismo momento en que aparece la ventana en pantalla, porque // hasta que se invoque por primera vez el mtodo paint(), no // se colocar una imagen en el contendor this.setVisible( true ); // Clase annima anidada que permite terminar la ejecucin del // programa, controlando el botn de cierre del Frame this.addWindowListener( new WindowAdapter() { public void windowClosing( WindowEvent evt ) { // Se sale al sistema System.exit( 0 ); } } ); } public static void main( String[] args ) { // Se instancia un objeto de la clase new java1518(); } // Se sobrecarga el mtodo para pintar la imagen public void paint( Graphics g ) { // Se traslada el origen para evitar el efecto del borde g.translate( this.getInsets().left,this.getInsets().top ); // Ahora se pinta la imagen a la mitad de su tamao g.drawImage( imagen,0,0, imagen.getWidth(this)/2,imagen.getHeight(this)/2,this ); }

} La imagen siguiente reproduce la ventana generada en la ejecucin del programa, que se repetir en los dems ejemplos, en donde se utilizan distintas formas de presentar lo mismo, por lo que sirva de referencia al lector esta imagen para ste y subsiguientes ejemplos.

Como el lector tambin supondr, lo que sigue ahora es la revisin de algunos de los trozos de cdigo del ejemplo que resultan ms interesantes. Aunque precisamente en este ejemplo, no sea especialmente interesante el detenerse porque es una simple presentacin y toma de contacto con la clase Image, pero s se pueden revisar aquellas partes que van a ser comunes en todos los ejemplos. As que, lo primero que debe observarse es la declaracin de la variable de instancia que es una variable de referencia de tipo Image, que ser la que posteriormente se utilice para manipular esa imagen. class java1518 extends Frame { Image imagen; // Referencia a un objeto Image El siguiente trozo de cdigo que aqu debe resaltarse es la sentencia en el constructor del contenedor, que utiliza el mtodo getImage() de la clase Toolkit para asociar el fichero muneco.gif con la variable de referencia imagen. imagen = Toolkit.getDefaultToolkit().getImage( "muneco.gif" ); Es importante hacer notar al lector que esta sentencia no hace que la imagen aparezca en pantalla en el momento en que el contenedor se haga visible. Las lneas de cdigo que puedan interesar hay que buscarlas ya en el mtodo paint(), en donde se invoca una de las versiones sobrecargadas del mtodo drawImage(), al cual se le indica en la lista de parmetros que se le pasa; en primer lugar, el nombre de la variable de referencia que apunta al fichero en disco que contiene la imagen, luego las coordenadas donde se debe colocar la esquina superior izquierda de la imagen, despus el ancho y alto que debe tener la imagen, y por fin, thiscomo objeto observador.

// Ahora se pinta la imagen a la mitad de su tamao g.drawImage( imagen,0,0, imagen.getWidth(this)/2,imagen.getHeight(this)/2,this ); Los mtodos getWidth() y getHeight() de la clase Image, se han utilizado para determinar el tamao original de la imagen, y hacer que se presente en pantalla reducida a la mitad, para que el ejemplo no sea muy soso. Observe el lector, que los parmetros que hay que pasar a estos mtodos es el observador, para que puedan indicarle las dimensiones de la imagen. El ejemplo siguiente, java1519.java, no proporciona un efecto visual demasiado bueno mientras se carga la imagen para presentarla en pantalla, que se corregir posteriormente al usar un objetoMediaTracker, para bloquear la tarea hasta que la imagen est totalmente cargada, con lo que se elimina el parpadeo que se produce al ir presentndose en la pantalla partes de esa imagen que no est totalmente cargada. El tiempo mximo de carga permitido es un segundo; si la imagen no se carga satisfactoriamente en un segundo, el programa presenta un mensaje indicando la circunstancia y sale. Una imagen grande, o una imagen que se cargue directamente desde Internet (que es una fuente muy lenta), puede necesitar ms tiempo. El cdigo completo del ejemplo es el que se reproduce a continuacin, y se revisa despus. import java.awt.*; import java.awt.event.*; // Clase de control del ejemplo class java1519 extends Frame { // Referencia a la imagen Image imagen; public java1519() { this.setTitle( "Tutorial de Java, Grficos" ); this.setSize( 275,250 ); // Recogemos en la variable "imagen" el fichero de imagen que // se indica, y que se supone situado en el mismo directorio y // disco que la clase del ejemplo imagen = Toolkit.getDefaultToolkit().getImage( "muneco.gif" ); // Se hace visible el Frame, que en la pantalla da origen a // la ventana, aunque la primera imagen no es visible en el // mismo momento en que aparece la ventana en pantalla, porque // hasta que se invoque por primera vez el mtodo paint(), no // se colocar una imagen en el contendor this.setVisible( true ); // Clase annima anidada que permite terminar la ejecucin del // programa, controlando el botn de cierre del Frame this.addWindowListener( new WindowAdapter() { public void windowClosing( WindowEvent evt ) { // Se sale al sistema System.exit( 0 ); }

} ); } public static void main( String[] args ) { // Se instancia un objeto de la clase new java1519(); } // Se sobrecarga el mtodo para pintar la imagen public void paint( Graphics g ) { // Se traslada el origen para evitar el efecto del borde g.translate( this.getInsets().left,this.getInsets().top ); // Se utiliza un objeto MediaTracker para bloquear la tarea hasta // que la imagen est cargada completamente, antes de intentar // pintarla en pantalla. Si la carga de la imagen falla en el // intervalo de un segundo, el programa se termina. Sin el uso de // un objeto de tipo MediaTracker, si la imagen es pequea, apenas // se notar el uso de MediaTracker, pero s que es importante a la // hora de cargar imgenes muy grandes o gran cantidad de ellas MediaTracker tracker = new MediaTracker( this ); // Se aade la imagen a la lista del tracker tracker.addImage( imagen,1 ); try { // Se bloquea la tarea durante un segundo, mientras se // intenta la carga de la imagen. En caso de que la imagen // sea mayor que la que se utiliza en este ejemplo, puede // ser necesario aumentar este tiempo if( !tracker.waitForID(1,1000) ) { System.out.println( "Fallo en la carga de la imagen" ); System.exit( 0 ); } } catch( InterruptedException e ) { System.out.println( e ); } // Ahora se pinta la imagen a la mitad de su tamao normal g.drawImage( imagen,0,0, imagen.getWidth(this)/2,imagen.getHeight(this)/2,this ); // Y se presenta en pantalla this.repaint(); } } Para revisar el cdigo del ejemplo, se prescindir de la parte que est duplicada con respecto a ejemplos anteriores, para ver solamente el cdigo nuevo. Para comenzar esta revisin, pues, lo primero en que hay que detenerse es en la sentencia que instancia un objeto de tipo MediaTracker. El parmetro del constructor es el objeto Component a quien pertenecen las imgenes que se van a controlar. En este caso es: MediaTracker tracker = new MediaTracker( this ); El siguiente cdigo interesante es la sentencia que incorpora una nueva imagen a la lista de imgenes a controlar. En este caso los parmetros a pasar son una referencia al fichero de la imagen

y un identificador que se utilizar posteriormente para saber el estado en que se encuentra la carga de la imagen; para este identificador se puede utilizar cualquier valor entero, teniendo en cuenta que este valor representa la prioridad de carga, siendo los valores ms bajos los que tienen ms alta prioridad. tracker.addImage( imagen, 1 ); Ahora hay que detenerse en la invocacin al mtodo waitForId() sobre el objeto controlador. En este caso, el identificador de la imagen que se est controlando es el parmetro a pasar. Tambin se pasa un valor de 1000 milisegundos como parmetro para hacer que el programa cese el bloqueo y termine si la carga de la imagen no se ha completado dentro de ese intervalo de tiempo. Este mtodo devuelve true si la imagen se ha cargado con xito y false en cualquier otro caso. Hay algunos otros mtodos que se pueden utilizar para este mismo propsito y que devuelven void, por lo que necesitan otras referencias para saber si la imagen se ha cargado bien. En este caso, el valor de retorno del mtodo waitForID() es utilizado para terminar el programa si la carga de la imagen falla (note el lector el operador "!" delante de la palabra tracker). Este mtodo tambin lanza un objeto InterruptedException si la carga no se puede completar en el intervalo de tiempo determinado; por ello, la llamada al mtodo debe ir encerrada en un bloque try-catch. try { // Se bloquea la tarea durante un segundo, mientras se // intenta la carga de la imagen. En caso de que la imagen // sea mayor que la que se utiliza en este ejemplo, puede // ser necesario aumentar este tiempo if( !tracker.waitForID(1,1000) ) { System.out.println( "Fallo en la carga de la imagen" ); System.exit( 0 ); } } catch( InterruptedException e ) { System.out.println( e ); } Finalmente, se utiliza el mtodo drawImage() para pintar la imagen sobre el contenedor, una vez cargada. Cuando el lector ejecute el programa ver que la sensacin visual es mucho mejor que la del ejemplo anterior porque solamente se realiza una operacin de dibujo para pintar la imagen completa. // Ahora se pinta la imagen a la mitad de su tamao normal g.drawImage( imagen,0,0, imagen.getWidth(this)/2,imagen.getHeight(this)/2,this ); Los dos ejemplos que se han visto eran bastante simples, aunque ilustraban una serie de conceptos muy importantes que estn involucrados en la manipulacin de imgenes. El ejemplo java1520.java, presenta algunos conceptos adicionales. Cuando se ejecuta este ejemplo, aparecen en la ventana cinco imgenes escaladas, para las cuales se ha utilizado el mtodo getScaledImage() de la claseImage a la hora de producir cada una de esas imgenes. El programa invoca al mtodo getImage() sobre un objeto de la clase Toolkit para asociar la referencia a un objeto Image llamado imagenFuente a un fichero que contiene la imagen en el disco duro. Luego se invoca el mtodo getScaledImage() sobre el objeto imagenFuente sucesivamente cinco veces para generar cinco instancias escaladas de esa imagen, utilizando un algoritmo diferente

para la obtencin de cada una de ellas. Se instancia un objeto MediaTracker en el mtodo sobrecargado paint(). El objeto imagenFuente y sus cinco instancias escaladas se aaden a la lista de imgenes que van a ser controladas por el objeto MediaTracker, teniendo todas ellas el mismo identificador, es decir, la misma prioridad. El mtodo waitForAll() de la clase MediaTacker es el que se utiliza en este caso para bloquear la tarea hasta que se cargan y escalan las imgenes. Durante esta carga, puede haber una pausa de unos 4 o 5 segundos, o incluso mayor, dependiendo de la mquina en que se ejecute el programa y de la complejidad de la imagen; sin embargo, a la hora de su aparicin en pantalla, no hay ninguna pausa, las cinco imgenes se presentan en pantalla simultneamente.

El cdigo completo del ejemplo es el que se presenta a continuacin, correspondiendo la imagen anterior a la ejecucin del mismo. import java.awt.*; import java.awt.event.*; class java1520 extends Frame { // Referencias a los objetos de tipo Image que se van a presentar en // pantalla Image imagenFuente,imagen1,imagen2,imagen3,imagen4,imagen5; // Contructor de la clase public java1520() { this.setTitle( "Tutorial de Java, Grficos" ); this.setSize( 415,260 ); // Se carga la imagen desde el fichero que se indique, que se // supone situado en el directorio actual del disco duro imagenFuente = Toolkit.getDefaultToolkit().getImage( "muneco.gif" ); // Se crean cinco instancias escaladas de la imagen anterior, todas // del mismo tamao pero utilizando un algoritmo diferente en el // escalado de cada una de ellas, para imagen1 = imagenFuente.getScaledInstance( 136,120,

Image.SCALE_AREA_AVERAGING ); imagen2 = imagenFuente.getScaledInstance( Image.SCALE_SMOOTH ); imagen3 = imagenFuente.getScaledInstance( Image.SCALE_FAST ); imagen4 = imagenFuente.getScaledInstance( Image.SCALE_REPLICATE ); imagen5 = imagenFuente.getScaledInstance( Image.SCALE_DEFAULT );

136,120, 136,120, 136,120, 136,120,

// Se hace visible el marco de la ventana. En este momento todava no // es visible ninguna de las imgenes que se han creado anteriormente this.setVisible(true); // Clase anidada que permite terminar la ejecucin de la animacin this.addWindowListener( // Definicin de la clase annima para controlar el cierre de // la ventana new WindowAdapter() { public void windowClosing( WindowEvent evt ) { // Se concluye el programa System.exit( 0 ); } } ); } // Mtodo de control del programa public static void main( String[] args ) { // Se instancia un objeto de esta clase new java1520(); } // Mtodo paint() sobreescrito public void paint( Graphics g ) { // Se traslada el origen para evitar el efecto del borde g.translate( this.getInsets().left,this.getInsets().top ); // Se utiliza un objeto MediaTracker para bloquear la tarea hasta // que las imgenes estn cargadas completamente, antes de intentar // pintarlas en pantalla. MediaTracker tracker = new MediaTracker( this ); // Se aaden las imgenes a la lista del tracker tracker.addImage( imagenFuente,1 ); tracker.addImage( imagen1,1 ); tracker.addImage( imagen2,1 ); tracker.addImage( imagen3,1 ); tracker.addImage( imagen4,1 ); tracker.addImage( imagen5,1 ); try{ // Se bloquea la tarea durante el tiempo necesario para la carga // de todas las imgenes tracker.waitForAll(); } catch( InterruptedException e ) { System.out.println( e );

} // Comprobamos si ha habido algn error en la carga de las imgenes // y su manipulacin. Si todo ha ido bien, las cinco imgenes // aparecern en pantalla simultneamente if( !tracker.isErrorAny() ) { g.drawImage( imagen1,0,0,this ); g.drawImage( imagen2,137,0,this ); g.drawImage( imagen3,275,0,this ); g.drawImage( imagen4,70,120,this ); g.drawImage( imagen5,210,120,this ); } else { System.out.println( "Error en la carga de imgenes" ); System.exit( 1 ); } } } A la hora de que las imgenes aparezcan en pantalla, no hay pausas aparentes entre una y otra. Si se utiliza el mtodo drawImage() para presentar y escalar la imagen al mismo tiempo, cosa que el lector puede realizar como ejercicio, se observan notables retrasos entre la presentacin de una imagen y la siguiente. En este caso, el primer cdigo en que merece detenerse es donde se utiliza el mtodo getImage()para asociar la variable de referencia imagenFuente con un fichero de imagen del disco duro. Esencialmente es lo mismo que en ejemplos anteriores; sin embargo, esa variable de referencia se utiliza para crear cinco instancias adicionales escaladas utilizando el mtodo getScaledInstance(), en cada una de cuales se utiliza un algoritmo de escalado distinto, especificado en el ltimo parmetro de la llamada al mtodo. La anchura y altura de la imagen escalada se indican en los dos primeros parmetros. Si alguno de ellos es -1, el tamao escalado en pixeles de esa dimensin de la imagen estar basado en el otro parmetro para mantener la misma relacin de aspecto que la imagen original. Si los dos parmetros son positivos, la imagen se escalar a las dimensiones que se indiquen en ellos. En ese caso, como muestran las lneas de cdigo siguientes, se pasa -1 como segundo parmetro en las cinco invocaciones al mtodo getScaledImage(), escalndolas adems al mismo tamao, utilizando algoritmos diferentes. // Se carga la imagen desde el fichero que se indique, que se // supone situado en el directorio actual del disco duro imagenFuente = Toolkit.getDefaultToolkit().getImage( "muneco.gif" ); // Se crean cinco instancias escaladas de la imagen anterior, todas // del mismo tamao pero utilizando un algoritmo diferente en el // escalado de cada una de ellas, para imagen1 = imagenFuente.getScaledInstance( 136,120, Image.SCALE_AREA_AVERAGING ); imagen2 = imagenFuente.getScaledInstance( 136,120, Image.SCALE_SMOOTH ); imagen3 = imagenFuente.getScaledInstance( 136,120, Image.SCALE_FAST );

imagen4 = imagenFuente.getScaledInstance( 136,120, Image.SCALE_REPLICATE ); imagen5 = imagenFuente.getScaledInstance( 136,120, Image.SCALE_DEFAULT ); El siguiente trozo interesante del ejemplo es el trozo del mtodo paint() donde se incorporan las seis referencias de tipo Image a la lista de imgenes que controlar el objeto MediaTracker. Las seis se aaden con el mismo nivel de prioridad. // Se utiliza un objeto MediaTracker para bloquear la tarea hasta // que las imgenes estn cargadas completamente, antes de intentar // pintarlas en pantalla. MediaTracker tracker = new MediaTracker( this ); // Se aaden las imgenes a la lista del tracker tracker.addImage( imagenFuente,1 ); tracker.addImage( imagen1,1 ); tracker.addImage( imagen2,1 ); tracker.addImage( imagen3,1 ); tracker.addImage( imagen4,1 ); tracker.addImage( imagen5,1 ); Las lneas siguientes muestran el bloque try-catch que bloquea la tarea hasta que las seis imgenes estn completamente cargadas y escaladas. try{ // Se bloquea la tarea durante el tiempo necesario para la carga // de todas las imgenes tracker.waitForAll(); } catch( InterruptedException e ) { System.out.println( e ); } El ltimo trozo de cdigo ms interesante es el que utiliza una versin sin escalado del mtododrawImage() para pintar las cinco imgenes escaladas previamente. Esto es importante, porque al no necesitar las imgenes ningn procesado, su aparicin en pantalla se realiza en un abrir y cerrar de ojos. En este caso tambin se ha utilizado el mtodo isErrorAny() (con el operador not) para confirmar que no se han producido errores al invocar al mtodo drawImage() para pintar las imgenes en pantalla. // Comprobamos si ha habido algn error en la carga de las imgenes // y su manipulacin. Si todo ha ido bien, las cinco imgenes // aparecern en pantalla simultneamente if( !tracker.isErrorAny() ) { g.drawImage( imagen1,0,0,this ); g.drawImage( imagen2,137,0,this ); g.drawImage( imagen3,275,0,this ); g.drawImage( imagen4,70,120,this ); g.drawImage( imagen5,210,120,this ); } else { System.out.println( "Error en la carga de imgenes" ); System.exit( 1 ); }

Se puede hablar de dos tipos: ~- Animacion de tipo dibujos animados: presentar una sucesion rapida de imagenes precargadas GIF o JPEG (p205 21days) ~- Animacion dibujada en tiempo real; veamos ~- Un ejemplo que NO funciona (no aparece nada en pantalla);

// MalRelojDigitalApplet.java import java.awt.Graphics; import java.awt.Font; import java.util.Date; public class MalRelojDigitalApplet extends java.applet.Applet { Font fuente = new Font("TimesRoman", Font.BOLD, 24); Date fecha; public void start() { while (true) { fecha = new Date(); repaint(); try { Thread.sleep(10000); } catch(InterruptedException e) {;} } } public void paint(Graphics g) { g.setFont(fuente); g.drawString(fecha.toString(), 10, 50); } }

~- Porqu no funciona?: paint nunca se ejecuta ya que el bucle while monopoliza la ejecucion. ~- Cmo debe hacerse para que funcione: usando Threads

Ej: // BienRelojDigitalApplet.java import java.awt.Graphics; import java.awt.Font; import java.util.Date; public class BienRelojDigitalApplet extends java.applet.Applet implements Runnable //cambio { Font fuente = new Font("TimesRoman", Font.BOLD, 24); Date fecha; Thread runner; //cambio //cambio public void start()

{ if (runner == null) { runner = new Thread(this); runner.start(); } else { System.out.println("Stop"); } } //cambio public void stop() { if (runner != null) { runner.stop(); runner = null; } else { System.out.println("Stop"); } } //cambio public void run() { while (true)

{ fecha = new Date(); repaint(); try { Thread.sleep(1000); } catch(InterruptedException e) {;} } } public void paint(Graphics g) { { g.setFont(fuente); g.drawString(fecha.toString(), 10, 50); } } }

~- El problema del parpadeo: el programa anterior funciona, pero se aprecia un parpadeo molesto cada 3 o 4 segundos ~- Porqu aparece parpadeo: ~~- (las imagenes son demasiado grandes. Con pequeos cuadros es inapreciable el parpadeo) ~~- repaint() llama al metodo update() ~~- update() borra la pantalla por completo y la rellena con el color de fondo. Despues llama a paint()

public void update(Graphics g) { g.setColor(getBackground()); g.fillRect(0,0,width,height); g.setColor(getForeground()); paint(g); } ~~- paint() escribe el nuevo pantallazo ~- Es la llamada a update() la que produce el parpadeo. ~- Soluciones posibles ~~1) Sobreescribir update() para que no borre la pantalla o que solo borre una cierta area ~~1) Clipping: re-dibujar solo aquello que cambia. Metodo clipRect() de la clase Graphics ~~1) Doble-buffering: hacer los cambios en una pantalla virtual y volcar el resultado a la pantalla real (p212 21days). Es el metodo mas complicado...

Visor de Imgenes

Visor de Imgenes
Este Applet es un pequeo visualizador de imgenes, lo que hace es mostrarnos en Miniatura unas imgenes, en la parte inferior y al momento de seleccionar una esta se visualiza en grande en la parte superior del Applet.

Imgenes

Cdigo Clase Principal


package Clases; import java.awt.BorderLayout; import java.awt.event.*; import javax.swing.*; public class Principal extends JApplet { panelVisorMiniaturas pm; panelVisualizador pv; public void init(){ pm=new panelVisorMiniaturas(this); pv=new panelVisualizador(this); add(pv); ImageIcon ImageIcon(this.getClass().getResource("../Imagenes/siguiente.png")); JButton btnsiguiente=new JButton(imgbotons); btnsiguiente.addActionListener(new ActionListener() {

imgbotons=new

@Override public void actionPerformed(ActionEvent e) { pm.siguienteImagen(); pm.quitarBorder(); } }); ImageIcon ImageIcon(this.getClass().getResource("../Imagenes/anterior.png")); JButton btnanterior=new JButton(imgbotona); btnanterior.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { pm.anteriorImagen(); pm.quitarBorder(); } }); JPanel pbotones=new JPanel(); pbotones.add(btnanterior); pbotones.add(pm); pbotones.add(btnsiguiente); add(pbotones,BorderLayout.SOUTH); } public panelVisorMiniaturas getPm() { return pm; } public void setPm(panelVisorMiniaturas pm) { this.pm = pm; } public panelVisualizador getPv() { return pv; } public void setPv(panelVisualizador pv) { this.pv = pv; } }

imgbotona=new

Clase panelVisualizador
package Clases; import java.awt.Graphics; import javax.swing.ImageIcon; import javax.swing.JPanel;

public class panelVisualizador extends JPanel { Principal p; ImageIcon imagen; public panelVisualizador(Principal prin){ p=prin; } public void paintComponent(Graphics g){ super.paintComponents(g); if(imagen!=null){ g.drawImage(imagen.getImage(),0 , 0, p.getPv().getWidth(), p.getPv().getHeight(), this); } } public Principal getP() { return p; } public void setP(Principal p) { this.p = p; } public ImageIcon getImagen() { return imagen; } public void setImagen(ImageIcon imagen) { this.imagen = imagen; } }

Clase panelVisorMiniaturas
package Clases; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JPanel; public class panelVisorMiniaturas extends JPanel { panelMiniatura paneles[]=new panelMiniatura[4];

ImageIcon imagenes[]=new ImageIcon[13]; int indices[]=new int[4]; Principal p; public panelVisorMiniaturas(Principal prin){ cargarImagenes(); p=prin; setLayout(new GridLayout(1, 4,10,10)); for(int i=0;i<4;i++){ paneles[i]=new panelMiniatura(imagenes[i],p); add(paneles[i]); } } public void siguienteImagen(){ if(indices[3]<12){ for(int i=0;i<4;i++){ indices[i]=indices[i]+1; paneles[i].setImagen(imagenes[indices[i]]); } repaint(); p.repaint(); } } public void anteriorImagen(){ if(indices[0]>0){ for(int i=0;i<4;i++){ indices[i]=indices[i]-1; paneles[i].setImagen(imagenes[indices[i]]); } repaint(); p.repaint(); } } public void cargarImagenes(){ for(int i=0;i<4;i++){ indices[i]=i; } for(int i=0;i<13;i++){ imagenes[i]=new ImageIcon(this.getClass().getResource("../Imagenes/"+(i+1)+".jpg")); } } public void quitarBorder(){ for(int i=0;i<4;i++){ paneles[i].setBorder(null); } } public panelMiniatura[] getPaneles() { return paneles;

} public void setPaneles(panelMiniatura[] paneles) { this.paneles = paneles; } public ImageIcon[] getImagenes() { return imagenes; } public void setImagenes(ImageIcon[] imagenes) { this.imagenes = imagenes; } public int[] getIndices() { return indices; } public void setIndices(int[] indices) { this.indices = indices; } }

Clase panelMiniatura
package Clases; import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import javax.swing.*; public class panelMiniatura extends JPanel { ImageIcon imagen; Principal p; public panelMiniatura(ImageIcon img,Principal prin){ imagen=img; p=prin; setPreferredSize(new Dimension(80,80)); MouseListener ml=new MouseListener() { public void mouseReleased(MouseEvent e) { } public void mousePressed(MouseEvent e) { } public void mouseExited(MouseEvent e) { }

@Override public void mouseEntered(MouseEvent e) { } @Override public void mouseClicked(MouseEvent e) { p.getPm().quitarBorder(); panelMiniatura pm=(panelMiniatura)e.getSource(); pm.setBorder(BorderFactory.createLineBorder(Color.ORANGE, 3)); p.getPv().setImagen(pm.getImagen()); p.getPv().repaint(); p.repaint(); } }; addMouseListener(ml); } public void paintComponent(Graphics g){ super.paintComponents(g); if(imagen!=null){ g.drawImage(imagen.getImage(), 0, 0, 80, 80, this); } } public ImageIcon getImagen() { return imagen; } public void setImagen(ImageIcon imagen) { this.imagen = imagen; } } El cdigo es claro, tengo en la clase principal un objeto panelVisualizador y un objeto panelVisorMiniaturas, ademas aqu coloco los botones de siguiente y anterior. Dentro de panelVisorMiniaturas estan unos objetos panelMiniatura la cual cada una tiene su imagen y la escale para que quedara 80 x 80 pixeles. Ademas a cada panelMiniatura le coloque un MouseListener para que cuando seleccionen un panelMiniatura este le mande la imagen a panelVisualizador y lo muestre en grande.

Applet

Este es un ejemplo de un applet, Animacion.java, que crea un thread de animacin que nos presenta el globo terrqueo en rotacin. Aqu podemos ver que estamos creando un thread de s mismo, concurrencia. Adems, animacion.start() llama al start() del thread, no del applet, que automticamente llamar a run():
import java.awt.*; import java.applet.Applet; public class Animacion extends Applet implements Runnable { Image imagenes[]; MediaTracker tracker; int indice = 0; Thread animacion; int maxAncho,maxAlto; Image offScrImage; // Componente off-screen para doble buffering Graphics offScrGC; // Nos indicar si ya se puede pintar boolean cargado = false; // Inicializamos el applet, establecemos su tamao y // cargamos las imgenes public void init() { // Establecemos el supervisor de imgenes tracker = new MediaTracker( this ); // Fijamos el tamao del applet maxAncho = 100; maxAlto = 100; imagenes = new Image[36]; // Establecemos el doble buffer y dimensionamos el applet try { offScrImage = createImage( maxAncho,maxAlto ); offScrGC = offScrImage.getGraphics(); offScrGC.setColor( Color.lightGray ); offScrGC.fillRect( 0,0,maxAncho,maxAlto ); resize( maxAncho,maxAlto ); } catch( Exception e ) { e.printStackTrace(); } // Cargamos las imgenes en un array for( int i=0; i < 36; i++ ) { String fichero = new String( "Tierra"+String.valueOf(i+1)+".gif" ); imagenes[i] = getImage( getDocumentBase(),fichero ); // Registramos las imgenes con el tracker tracker.addImage( imagenes[i],i ); } try { // Utilizamos el tracker para comprobar que todas las

// imgenes estn cargadas tracker.waitForAll(); } catch( InterruptedException e ) { ; } cargado = true; } // Pintamos el fotograma que corresponda public void paint( Graphics g ) { if( cargado ) g.drawImage( offScrImage,0,0,this ); } // Arrancamos y establecemos la primera imagen public void start() { if( tracker.checkID( indice ) ) offScrGC.drawImage( imagenes[indice],0,0,this ); animacion = new Thread( this ); animacion.start(); } // Aqu hacemos el trabajo de animacin // Muestra una imagen, para, muestra la siguiente... public void run() { // Obtiene el identificador del thread Thread thActual = Thread.currentThread(); // Nos aseguramos de que se ejecuta cuando estamos en un // thread y adems es el actual while( animacion != null && animacion == thActual ) { if( tracker.checkID( indice ) ) { // Obtenemos la siguiente imagen offScrGC.drawImage( imagenes[indice],0,0,this ); indice++; // Volvemos al principio y seguimos, para el bucle if( indice >= imagenes.length ) indice = 0; } // Ralentizamos la animacin para que parezca normal try { animacion.sleep( 200 ); } catch( InterruptedException e ) { ; } // Pintamos el siguiente fotograma repaint(); } } }

En el ejemplo podemos observar ms cosas. La variable thActual es propia de cada thread que se lance, y la variable animacion la estarn viendo todos los

threads. No hay duplicidad de procesos, sino que todos comparten las mismas variables; cada thread, sin embargo, tiene su pila local de variables, que no comparte con nadie y que son las que estn declaradas dentro de las llaves del mtodo run(). La excepcin InterruptedExcepcion salta en el caso en que se haya tenido al thread parado ms tiempo del debido. Es imprescindible recoger esta excepcin cuando se estn implementando threads, tanto es as, que en el caso de no recogerla, el compilador generar un error.

Das könnte Ihnen auch gefallen