2010-02-09 9 views
23

J'ai une classe qui hérite de JPanel avec une image dessus et je veux mettre en place une petite animation pour afficher le panneau/image et ensuite l'éteindre quand un événement se déclenche.Comment estomper une image en mode swing?

Je suppose que j'ai mis en place un thread et déclenché l'animation, mais comment puis-je faire le fondu?

Répondre

14

Vous pouvez effectuer vous-même le filetage, mais il est peut-être plus facile d'utiliser la bibliothèque Trident pour le gérer. Si vous créez un setter sur votre classe appelée (disons, setOpacity), vous pouvez demander à trident d'interpoler le champ "opacity" de 1.0 à 0.0 sur une période de temps spécifique (voici some of the docs sur l'utilisation de Trident). Lorsque vous peignez l'image, vous pouvez faire la transparence avec un AlphaComposite, en utilisant la valeur "opacité" mise à jour pour le paramètre alpha du composite. Il y a un tutoriel de Sun qui inclut un alpha composite example.

+1

@Ash: +1, j'allais vous suggérons d'utiliser AlphaComposite. – SyntaxT3rr0r

+0

Trident facilite-t-il également l'interpolation? – blank

+0

Je crois qu'il fait une interpolation linéaire (principalement?), Basé sur ce billet de blog par l'auteur de Trident (avant-dernier paragraphe): http://www.pushing-pixels.org/?p=1599 – Ash

6

Il existe quelques informations utiles décrivant la transparence de l'image here.

Votre approche serait quelque chose comme ceci:

  • Définir une balançoire Timer pour tirer un ActionEvent sur le fil Dispatch événement toutes les millisecondes N.
  • Ajouter un ActionListener au Timer qui devrait appeler repaint() sur votre Component contenant le Image.
  • Remplacer la méthode de paintComponent(Graphics)Component effectuer les opérations suivantes:
    • Cast l'objet Graphics à un Graphics2D.
    • Définissez un AlphaComposite sur Graphics2D en utilisant setComposite. Cela contrôle le niveau de transparence.
    • Dessinez l'image.

Pour chaque itération de votre fondu animation vous changeriez les valeurs du AlphaComposite pour rendre l'image plus transparente.

+0

Mon composant est un composant enfant, lorsque j'ai utilisé paintComponent, il a peint le parent entier dans le JPanel, en remplaçant la peinture (Graphics g) à la place. Est-ce exact? – blank

12

Voici un exemple utilisant la transparence alpha. Vous pouvez utiliser this composite tool pour voir le résultat de l'utilisation de couleurs, de modes et d'alphas différents.

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

A titre de comparaison, voir cet exemple [http: // stackoverflow.com/questions/2123841/javax-swing-timer-répétitions-fine-mais-actionlistener-doesnt-do-anything/2124507 # 2124507) qui varie la saturation de la couleur d'arrière-plan. – trashgod