Voilà le compte rendu de ce que nous avons :
- une classe héritée de JFrame
- une classe héritée de JPanel dans laquelle nous faisons de zolis dessins. Un rond en l'occurrence...
Avec ces deux classes, nous allons pouvoir créer un effet de déplacement.
Vous avez bien entendu

: j'ai dit un
effet de déplacement !
En réalité, le principe réside dans le fait que vous allez donner des coordonnées différentes à votre rond, et vous allez forcer votre objet
Panneau à se redessiner ! Tout ceci,
vous l'aviez deviné, dans une boucle !
Nous allons donc nous préparer à ces nouveautés !
Jusqu'à présent, nous avons utilisé des valeurs fixes pour les coordonnées de notre rond, et il va falloir dynamiser tout ça...
Nous allons donc créer deux variables privées de type
int dans notre classe
Panneau : appelons-les
posX et
posY.
Pour l'animation que nous allons travailler, notre rond devra provenir de l'extérieur de notre fenêtre. Partons du principe que celui-ci va faire 50 pixels de diamètre : il faudra donc que notre panneau peigne ce rond en dehors de sa zone d'affichage, nous initialiserons donc nos deux variables d'instance à
-50.
Voilà à quoi ressemble notre classe, maintenant :
Code : Java 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 | import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Panneau extends JPanel {
private int posX = -50;
private int posY = -50;
public void paintComponent(Graphics g){
g.setColor(Color.red);
g.fillOval(posX, posY, 50, 50);
}
public int getPosX() {
return posX;
}
public void setPosX(int posX) {
this.posX = posX;
}
public int getPosY() {
return posY;
}
public void setPosY(int posY) {
this.posY = posY;
}
}
|
Il ne nous reste plus qu'à faire en sorte que notre rond se déplace : il nous faut donc un moyen de changer les coordonnées de celui-ci, le tout dans une boucle. Nous allons ainsi ajouter une méthode privée dans notre classe
Fenetre afin de gérer tout cela ; nous appellerons celle-ci en dernier dans notre constructeur. Voici donc à quoi ressemble notre classe
Fenetre :
Code : Java 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 | import java.awt.Dimension;
import javax.swing.JFrame;
public class Fenetre extends JFrame{
private Panneau pan = new Panneau();
public Fenetre(){
this.setTitle("Animation");
this.setSize(300, 300);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setContentPane(pan);
this.setVisible(true);
go();
}
private void go(){
for(int i = -50; i < pan.getWidth(); i++)
{
int x = pan.getPosX(), y = pan.getPosY();
x++;
y++;
pan.setPosX(x);
pan.setPosY(y);
pan.repaint();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
|
Hep ! Qu'est-ce que c'est que ces deux instructions à la fin de la méthode go() ?
Tout d'abord, je pense que, les deux dernières instructions mises à part, vous ne devez pas avoir trop de mal à comprendre ce code.
La première des deux nouvelles instructions est
pan.repaint(). Cette dernière donne l'ordre à votre composant, ici un
JPanel,
de se redessiner.
La toute première fois, dans le constructeur de notre classe
Fenetre, votre composant invoque la méthode
paintComponent et dessine un rond aux coordonnées que vous lui avez spécifiées. La méthode
repaint() ne fait rien d'autre que de faire à nouveau appel à la méthode
paintComponent ; mais avant, vous avez changé les coordonnées du rond par le biais des accesseurs créés précédemment. Donc à chaque tour de boucle, les coordonnées de notre rond vont changer.
La deuxième instruction est en fait un moyen de
faire une pause dans votre code...

Celle-ci met en attente votre programme pendant un laps de temps défini dans la méthode
sleep(), ce temps est exprimé en millièmes de secondes (plus le temps d'attente est court, plus votre animation sera rapide

).
Thread est en fait un objet qui permet de créer un nouveau processus dans un programme, ou de gérer le processus principal.
Dans tous les programmes,
il y a au moins un processus, celui qui est en cours d'exécution. Mais vous verrez plus tard qu'il est possible de diviser certaines tâches en plusieurs processus afin de ne pas avoir de perte de temps et de performances dans vos programmes. Pour le moment, sachez que vous pouvez faire des pauses dans vos programmes avec cette instruction :
Code : Java1
2
3
4
5
6
7 | try{
Thread.sleep(1000);//Ici une pause d'une seconde
}catch(InterruptedException e) {
e.printStackTrace();
}
|
Cette instruction est dite "à risque", vous devez donc l'entourer d'un bloc try{}catch(){} afin de capturer les exceptions potentielles ! Sinon : ERREUR DE COMPILATION !
Maintenant que toute la lumière est faite sur cette affaire, exécutez votre code, et vous obtenez :
Bien sûr, cette image est le résultat final, vous devriez avoir vu votre rond bouger mais au lieu d'être clair, il a laissé une trainée derrière lui...
Pourquoi ?
C'est simple : vous avez demandé à votre objet
Panneau de se redessiner, mais il a gardé les précédents passages de votre rond sur lui-même ! Pour résoudre ce problème, il suffit d'effacer ceux-ci avant de redessiner votre rond.
Comment fait-on ça ?
Il vous suffit de dessiner un rectangle, d'une quelconque couleur, prenant toute la surface disponible, avant de dessiner votre rond. Voici le code de notre classe
Panneau mis à jour :
Code : Java 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 | import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Panneau extends JPanel {
private int posX = -50;
private int posY = -50;
public void paintComponent(Graphics g){
//On décide d'une couleur de fond pour notre rectangle
g.setColor(Color.white);
//On dessine celui-ci afin qu'il prenne tout la surface
g.fillRect(0, 0, this.getWidth(), this.getHeight());
//On redéfinit une couleur pour notre rond
g.setColor(Color.red);
//On le dessine aux coordonnées souhaitées
g.fillOval(posX, posY, 50, 50);
}
public int getPosX() {
return posX;
}
public void setPosX(int posX) {
this.posX = posX;
}
public int getPosY() {
return posY;
}
public void setPosY(int posY) {
this.posY = posY;
}
}
|
Voici trois captures d'écran prises à différents moments de l'animation :
Je pense qu'il est temps d'améliorer encore notre animation... Est-ce que ça vous dirait que celle-ci continue tant que vous ne fermez pas votre fenêtre ?

Oui ? Alors continuons.