Thread pour une animation dans un JPanel
Salut tout le monde,
J'ai le code suivant :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class PanelAnimation extends JPanel {
// Un tableau d'images
private BufferedImage[] tableauImages = null;
// Un nombre d'images
public static final int NOMBRE_IMAGES = 7;
// L'image en cours
private BufferedImage imageEnCours = null;
// Le Timer pour l'animation
private Timer minuteur = null;
// La tâche du minuteur
private TimerTask tache = null;
public PanelAnimation() {
// On associe un layout
this.setLayout(new BorderLayout());
// On associe une taille au panelAnimation
this.setPreferredSize(new Dimension(200, 200));
// On déclare le tableau d'images (7 images)
tableauImages = new BufferedImage[NOMBRE_IMAGES];
// On charge les images
chargeImages();
// On instancie l'image en cours par défaut
imageEnCours = tableauImages[0];
// On instancie un minuteur pour l'animation
minuteur = new Timer();
// On définit une tâche pour le minuteur
tache = new TimerTask() {
// On lance l'animation dans un nouveau Thread
@Override
public void run() {
// On lance l'animation
lanceAnimation();
}
};
// On définit l'emploi du temps du minuteur :
// - suivre la tâche lanceAnimation()
// - à partir de maintenant
// - toutes les 50ms
minuteur.schedule(tache, 0, 50);
}
public void chargeImages() {
// Pour toutes les images
for (int i = 0; i < NOMBRE_IMAGES; i++) {
try {
// On charge l'image
tableauImages[i] = ImageIO.read(new File("./src/fr/" +
"apreslaclasse/alcgged/images/" + i + ".jpg"));
} catch (IOException exception) {
// On affiche la pile d'appel
exception.printStackTrace();
// On affiche un message
System.out.println("L'image " + i + ".jpg " +
"n'a pas été lue");
} catch (IllegalArgumentException exception) {
// On affiche la pile d'appel
exception.printStackTrace();
// On affiche un message
System.out.println("Le fichier image " + i + ".jpg " +
"est null");
} catch (NullPointerException exception) {
// On affiche la pile d'appel
exception.printStackTrace();
// On affiche un message
System.out.println("L'image " + i + ".jpg " +
"n'a pas été trouvée");
}
}
}
public void lanceAnimation() {
// TODO: Faire ça dans une boucle
// Si l'image en cours est la première image
if (imageEnCours.equals(tableauImages[0])) {
// On change l'image en cours
imageEnCours = tableauImages[1];
// On affiche l'image
this.repaint();
// Si l'image en cours est la seconde image
} else if (imageEnCours.equals(tableauImages[1])) {
// On change l'image en cours
imageEnCours = tableauImages[2];
// On affiche l'image
this.repaint();
// Si l'image en cours est la troisième image
} else if (imageEnCours.equals(tableauImages[2])) {
// On change l'image en cours
imageEnCours = tableauImages[3];
// On affiche l'image
this.repaint();
// Si l'image en cours est la quatrième image
} else if (imageEnCours.equals(tableauImages[3])) {
// On change l'image en cours
imageEnCours = tableauImages[4];
// On affiche l'image
this.repaint();
// Si l'image en cours est la cinquième image
} else if (imageEnCours.equals(tableauImages[4])) {
// On change l'image en cours
imageEnCours = tableauImages[5];
// On affiche l'image
this.repaint();
// Si l'image en cours est la sixième image
} else if (imageEnCours.equals(tableauImages[5])) {
// On change l'image en cours
imageEnCours = tableauImages[6];
// On affiche l'image
this.repaint();
// Si l'image en cours est la septième image
} else if (imageEnCours.equals(tableauImages[6])) {
// On change l'image en cours
imageEnCours = tableauImages[0];
// On affiche l'image
this.repaint();
// ICI : tache.cancel();
}
}
@Override
public void paintComponent(Graphics g) {
// On affiche l'image en cours dans le panel
g.drawImage(imageEnCours, 0, 0, this);
}
} |
J'ai une animation dans un JPanel. J'utilise un Timer.
A partir du Thread du TimerTask, je lance une méthode (lanceAnimation()).
Quand j'exécute mon code comme cela, je vois bien l'animation qui fait des tours et des tours de boucle. Mais du coup, le Thread ne s'arrête plus ! A un moment, plus tard dans le code, je ferme la fenêtre qui gère ce JPanel (avec dispose()) mais le Thread continue encore de tourner ! Pourquoi ?
Sinon, si je mets le code suivant : tache.cancel(); au commentaire rouge (voir plus haut dans mon code), l'animation fait un tour et s'arrête, le Thread a l'air également de s'arrêter. Cependant, c'est comme si le Thread lançait l'animation à partir de la méthode lanceAnimation() 7 fois (autant que le nombre d'images)... Bizarre, non ?