2010-02-09 14 views
23

Tengo clase que hereda de JPanel con una imagen y quiero configurar una pequeña animación para mostrar el panel/imagen y luego fundirla cuando se dispara un evento.¿Cómo puedo fundir una imagen en el swing?

Probablemente configuré un hilo y desencadené la animación, pero ¿cómo realizo el fundido?

Respuesta

14

Puede hacer el enhebrado usted mismo, pero podría ser más fácil utilizar la biblioteca Trident para manejarlo. Si creas un setter en tu clase llamada (digamos, setOpacity), puedes pedirle a Trident que interpole el campo "opacidad" de 1.0 a 0.0 durante un período de tiempo específico (aquí está some of the docs sobre cómo usar Trident).

Cuando está pintando la imagen, puede hacer la transparencia con AlphaComposite, utilizando el valor de "opacidad" actualizado para el parámetro alfa del compuesto. Hay un tutorial de Sun que incluye un alpha composite example.

+1

@Ash: 1, que iba a sugerir el uso de AlphaComposite. – SyntaxT3rr0r

+0

¿Trident también "facilita" la interpolación? – blank

+0

Creo que tiene interpolación lineal (¿en su mayoría?), Basada en esta publicación del blog del autor de Trident (penúltimo párrafo): http://www.pushing-pixels.org/?p=1599 – Ash

6

Hay información útil que describe la transparencia de la imagen here.

Su enfoque sería algo como esto:

  • definir una oscilación Timer despedir a un ActionEvent en el hilo de distribución de eventos cada N milisegundos.
  • Agregue ActionListener al Timer que debe llamar repaint() en su Component que contiene Image.
  • Anulación paintComponent(Graphics) método de la Component 's para hacer lo siguiente:
    • convertir el objeto a una GraphicsGraphics2D.
    • Establezca AlphaComposite en el Graphics2D utilizando setComposite. Esto controla el nivel de transparencia.
    • Dibuja la imagen.

Para cada iteración de la animación de fundido de salida tendría que cambiar los valores de la AlphaComposite para hacer la imagen más transparente.

+0

Mi componente es un componente secundario, cuando usé paintComponent, pinté el elemento primario dentro del JPanel, reemplazando la pintura (Graphics g) en lugar de eso lo solucioné. ¿Es eso correcto? – blank

12

Aquí hay un ejemplo con transparencia alfa. Puede usar this composite tool para ver el resultado del uso de diferentes colores, modos y alfas.

image

import java.awt.*; 
import java.awt.event.*; 
import java.awt.event.ActionListener; 
import javax.swing.*; 

public class AlphaTest extends JPanel implements ActionListener { 

    private static final Font FONT = new Font("Serif", Font.PLAIN, 32); 
    private static final String STRING = "Mothra alert!"; 
    private static final float DELTA = -0.1f; 
    private static final Timer timer = new Timer(100, null); 
    private float alpha = 1f; 

    AlphaTest() { 
     this.setPreferredSize(new Dimension(256, 96)); 
     this.setOpaque(true); 
     this.setBackground(Color.black); 
     timer.setInitialDelay(1000); 
     timer.addActionListener(this); 
     timer.start(); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2d = (Graphics2D) g; 
     g2d.setFont(FONT); 
     int xx = this.getWidth(); 
     int yy = this.getHeight(); 
     int w2 = g.getFontMetrics().stringWidth(STRING)/2; 
     int h2 = g.getFontMetrics().getDescent(); 
     g2d.fillRect(0, 0, xx, yy); 
     g2d.setComposite(AlphaComposite.getInstance(
      AlphaComposite.SRC_IN, alpha)); 
     g2d.setPaint(Color.red); 
     g2d.drawString(STRING, xx/2 - w2, yy/2 + h2); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     alpha += DELTA; 
     if (alpha < 0) { 
      alpha = 1; 
      timer.restart(); 
     } 
     repaint(); 
    } 

    static public void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       JFrame f = new JFrame(); 
       f.setLayout(new GridLayout(0, 1)); 
       f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       f.add(new AlphaTest()); 
       f.add(new AlphaTest()); 
       f.add(new AlphaTest()); 
       f.pack(); 
       f.setVisible(true); 
      } 
     }); 
    } 
} 
+1

Para la comparación, vea este [ejemplo] (http: // stackoverflow.com/questions/2123841/javax-swing-timer-repeats-fine-but-actionlistener-doesnt-do-anything/2124507 # 2124507) que varía la saturación del color de fondo. – trashgod

Cuestiones relacionadas