2012-05-31 21 views
9

Un GIF animado (cíclico) puede mostrarse en un JLabel o en HTML (en componentes de texto formateado como JEditorPane) y se puede ver que cíclica.Muestra un BG animado en Swing

Pero para cargar una imagen para pintar como fondo de un contenedor, normalmente usaría ImageIO.read() o Toolkit.getImage() (esta última cuando me siento nostálgico por el último milenio). Ninguno de los métodos para cargar una imagen da como resultado una imagen cíclica, por lo general es solo el primer cuadro.

Cómo cargar una imagen animada como fondo?

Respuesta

10

usando ImageIcon es probablemente la cosa más fácil de hacer. Un par de cosas a tener en cuenta:

  • ImageIcon(URL) sí mismo hace uso de Toolkit.getImage(URL). Puede preferir usar Toolkit.createImage(URL) en su lugar - getImage() puede usar datos de imagen en caché o compartidos.

  • ImageIcon utiliza un MediaTracker para esperar efectivamente hasta que la imagen esté completamente cargada.

Por lo tanto, el problema no puede ser el uso de Toolkit (ImageIO es un animal diferente), sino más bien el hecho de que usted no está haciendo una imagen completamente cargado. Una cosa interesante intentar sería:

Image image = f.getToolkit().createImage(url); 
//... 
ImagePanel imagePanel = new ImagePanel(image); 
imagePanel.prepareImage(image, imagePanel); 
//... 

Mi swing/AWT/J2D pueden ser un poco borrosa, pero la idea es que desde su ImagePanel es un ImageObserver, puede ser notificada de forma asíncrona sobre información de la imagen. El método Component.imageUpdate() debe invocar repaint según sea necesario.

Editar:

Como se señaló en los comentarios, no se requiere la llamada a prepareImage - un ejemplo de trabajo se incluye a continuación. La clave es que el método Oreemplazado invoca Graphics.drawImage, que proporciona el gancho ImageObserver. El método imageUpdate (implementado en java.awt.Component) se invocará continuamente con el indicador ImageObserver.FRAMEBITS establecido.

import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.GridLayout; 
import java.awt.Image; 
import java.awt.image.ImageObserver; 
import java.net.MalformedURLException; 
import java.net.URL; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.border.EmptyBorder; 

public class ImagePanel extends JPanel { 

    private final Image image; 

    public ImagePanel(Image image) { 
     super(); 
     this.image = image; 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     g.drawImage(this.image, 0, 0, getWidth(), getHeight(), this); 
    } 

    public static void main(String[] args) throws MalformedURLException { 
     final URL url = new URL("http://pscode.org/media/starzoom-thumb.gif"); 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       JFrame f = new JFrame("Image"); 
       f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       f.setLocationByPlatform(true); 

       Image image = f.getToolkit().createImage(url); 
       ImagePanel imagePanel = new ImagePanel(image); 
       imagePanel.setLayout(new GridLayout(5, 10, 10, 10)); 
       imagePanel.setBorder(new EmptyBorder(20, 20, 20, 20)); 
       for (int ii = 1; ii < 51; ii++) { 
        imagePanel.add(new JButton("" + ii)); 
       } 

       f.setContentPane(imagePanel); 
       f.pack(); 
       f.setVisible(true); 
      } 
     }); 
    } 
} 
+0

Gran captura. Probado 'Toolkit.createImage (URL)' como un reemplazo directo 'drop-in' para 'new ImageIcon (url) .getImage()' y la imagen también se recicló. Tenga en cuenta que no me molesté en llamar a 'prepareImage'. –

+0

Editaré mi respuesta mañana, pero también noté que la prueba que creé (una versión modificada de su código) no requirió la llamada a prepareImage. Creo que la llamada a Graphics.drawImage proporciona el gancho ImageObserver ... – kschneid

+0

Solo noté la edición justo ahora. ¡Pensé que esta podría ser mi primera sesión de preguntas y respuestas canónicas, pero resulta que tu respuesta es mejor! No estoy seguro si estar irritado por ser derrotado, o encantado de encontrar a alguien con más detalles. (Considera unos momentos más ...) De acuerdo, estoy encantado. Gracias por tu respuesta. :) –

14

Para obtener un GIF de ciclismo (animado) para la pintura personalizada, un truco es cargarlo usando un ImageIcon. Si bien la imagen devuelta por cualquiera de los dos métodos enumerados en la pregunta es estática, la que se obtiene de ImageIcon está animada.

El código siguiente agregará 50 botones, y luego, poco después, los marcos de las 'estrellas zoom' animadas GIF como BG. El ImagePanel extenderá la imagen al tamaño del panel.

  1. Se basa en esta imagen.

Zooming Stars GIF

import java.awt.*; 
import javax.swing.*; 
import javax.swing.border.EmptyBorder; 
import java.net.URL; 

class ImagePanel extends JPanel { 

    private Image image; 

    ImagePanel(Image image) { 
     this.image = image; 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     g.drawImage(image,0,0,getWidth(),getHeight(),this); 
    } 

    public static void main(String[] args) throws Exception { 
     URL url = new URL("http://i.stack.imgur.com/iQFxo.gif"); 
     final Image image = new ImageIcon(url).getImage(); 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       JFrame f = new JFrame("Image"); 
       f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       f.setLocationByPlatform(true); 

       ImagePanel imagePanel = new ImagePanel(image); 
       imagePanel.setLayout(new GridLayout(5,10,10,10)); 
       imagePanel.setBorder(new EmptyBorder(20,20,20,20)); 
       for (int ii=1; ii<51; ii++) { 
        imagePanel.add(new JButton("" + ii)); 
       } 

       f.setContentPane(imagePanel); 
       f.pack(); 
       f.setVisible(true); 
      } 
     }); 
    } 
} 
+0

por publicar un [SSCCE] (http://sscce.org/) – mKorbel

+0

Gracias por este bonito SSCCE, no sabía que ImageIcon podía mostrar la animación de un archivo .gif. Estaba debatiendo si debería agregar una imagen animada a mi GUI y ahora sé que será bastante simple si quiero agregarla. – WilliamShatner

1

me las arreglé para conseguir el gif animado dentro de mis JPanel esta manera:

private JPanel loadingPanel() { 
    JPanel panel = new JPanel(); 
    BoxLayout layoutMgr = new BoxLayout(panel, BoxLayout.PAGE_AXIS); 
    panel.setLayout(layoutMgr); 

    ClassLoader cldr = this.getClass().getClassLoader(); 
    java.net.URL imageURL = cldr.getResource("img/spinner.gif"); 
    ImageIcon imageIcon = new ImageIcon(imageURL); 
    JLabel iconLabel = new JLabel(); 
    iconLabel.setIcon(imageIcon); 
    imageIcon.setImageObserver(iconLabel); 

    JLabel label = new JLabel("Loading..."); 
    panel.add(iconLabel); 
    panel.add(label); 
    return panel; 
} 

Algunos puntos de este enfoque:
1. El archivo de imagen se encuentra dentro de la jarra;
2. ImageIO.read() devuelve una Imagen Buffered, que no actualiza el ImageObserver;
3. Otra alternativa para encontrar imágenes que se incluyen en el archivo jar es pedirle al cargador de clases de Java, el código que cargó su programa, que obtenga los archivos. Sabe dónde están las cosas.

Al hacerlo, pude obtener mi gif animado dentro de mi JPanel y funcionó a las mil maravillas.