Animation dans un jpanel + surveillance de la souris et du clavier

Soyez le premier à donner votre avis sur cette source.

Vue 7 307 fois - Téléchargée 886 fois

Description

Un mini-jeu "ClickOnTheYellowSquare" qui montre comment faire une petite animation 2D avec un JPanel (+ comment dessiner des éléments). La source montre aussi comment utiliser le MouseEvent et le MouseListener : le jeu va compter le nombre de clics effectués à gauche, à droite et sur le carré jaune.
Un carré rouge est dessiné au centre de la moitié gauche et un rond bleu est dessiné au centre de la moitié droite. Une ligne est tracée à la moitié pour séparer les 2.

De plus, une classe "EcouteClavier" va écouter le clavier et sitôt que le "mot magique" est tapé (ici, 'javafr'), une Jdialog s'ouvre en affichant un message.

J'ai codé cette source pour moi-même apprendre comment utiliser l'objet Graphic et Graphic2D.

Dans la classe Panneau, on peut ajouter des Carre.
Attention, si vous mettez beaucoup de carrés, cela risque de "lagger", d'avoir des ralentissements.

Source / Exemple :


package jeu;

import java.util.ArrayList;
import javax.swing.JFrame;

public class Fenetre extends JFrame {

Panneau pan = new Panneau();

     public Fenetre(int longueur, int largeur){

         this.setTitle("Click On The Yellow Square");
         this.setSize(longueur, largeur);
         // se positionne au centre
         this.setLocationRelativeTo(null);
         // Ferme-toi lorsqu'on clique sur "Fermer" !
         this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

         //On prévient notre JFrame que ce sera notre JPanel qui sera son contentPane

         this.setContentPane(pan);

         addKeyListener(new EcouteClavier());
         // this.setAlwaysOnTop(true);

         
        this.pack();

        this.setDefaultLookAndFeelDecorated(true);
        this.setExtendedState(this.MAXIMIZED_BOTH);

         this.setVisible(true);

         go();
     }

        private void go(){

                ArrayList list = pan.getListeCarres();
                Object[] tmp = list.toArray();

               while(true){
                        for(int i=0;i<tmp.length;i++)
                        {
                            Carre c = (Carre) tmp[i];

                            int x = c.getPosX(), y = c.getPosY();
                        //Si la coordonnée x est inférieure à 1, on avance
                        if(x < 1)  c.setBackX(false);
                        //Si la coordonnée x est supérieure à la taille du Panneau
                        //moins la taille du carre, on recule
                        if(x > pan.getWidth()- c.getLargeur()) c.setBackX(true);

                        //idem pour l'axe Y
                        if(y < 1) c.setBackY(false);
                        if(y > pan.getHeight()-c.getHauteur()) c.setBackY(true);

                        //Si on avance, on incrémente la coordonnée
                        if(!c.getBackX())
                                c.setPosX(++x);
                        //Sinon, on décrémente
                        else
                                c.setPosX(--x);

                        //Idem pour l'axe Y
                        if(!c.getBackY())
                                c.setPosY(++y);
                        else
                                c.setPosY(--y);

                        } // fin du for

                    
                     try {
                                Thread.sleep(15);
                     } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                     }

                        //On redessine notre Panneau
                     pan.repaint();
                 } // fin du while 
        }
}

Conclusion :


Une petite source assez bête mais qui montre une utilisation simple des Graphic, Graphic2D, MouseListener et KeyListener.

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

Messages postés
491
Date d'inscription
samedi 20 mai 2006
Statut
Membre
Dernière intervention
15 juillet 2012
9
La méthode "repaint" avec les arguments qui définissent le rectangle à redessiner existe dans la classe JComponent. Il n'y a donc rien à redéfinir.
Effectvement, dans la boucle "for" on appelle des "repaint" multiples sur le "Panneau". Quand des repaint() multiples sont appelé sur un composant avant que le premier appel ne soit traité, le Repaintmanager de Swing peut réunir les appels multiples en un seul appel. Donc cela ne risque pas de faire "beaucoup". Quand des appels multiples sont ainsi réunis, le rectangle "clip" résultant est égal à la réunion des rectangles qui sont contenus dans les appels réunis.
Messages postés
34
Date d'inscription
lundi 11 septembre 2006
Statut
Membre
Dernière intervention
19 février 2010

Merci pour votre commentaire et explication Uhrand.

Cependant, si on appelle repaint() avec de tels paramètres, il faut la redéfinir je suppose ?

Et, si j'ai bien compris, on appellerait cette méthode à chaque itération pour chaque carré ? Cela ne risque pas de faire "beaucoup" ?

Merci de votre aide :-)
Messages postés
491
Date d'inscription
samedi 20 mai 2006
Statut
Membre
Dernière intervention
15 juillet 2012
9
Voici quelques réflections au sujet de l'utlisation des threads dans ton exemple. Premièrement, une application Swing doit toujours démarrer sur le "EventDispatchThread" en utilisant la méthode "invokeLater":
public static void main(String[] args) {
    Runnable gui = new Runnable() {
        public void run() {
            int largeur = 200;
            int hauteur = 200;
            new Fenetre(largeur, hauteur);
        }
    };
    SwingUtilities.invokeLater(gui);
}

Ensuite, pour réaliser l'animation, on utilise un thread d'arrière plan. Par exemple:
new Thread(new Runnable() {
    public void run() {
        go();
    }
}).start();

Dans le thread d'arrière plan, les modifications de l'interface graphique doivent de nouveau être envoyées vers le "EventDispatchThread". Pour ce faire, on utilise généralement la méthode "invokeLater" (ou "invokeAndWait"). Cependant, il existe un petit nombre de méthodes Swing qui font ça automatiquement. On dit également que ces méthodes sont "thread safe". La méthode "repaint" en est un exemple. Cependant, dans la méthode "go", c'est préférable de déplacer le "repaint" vers l'intérieur de la boucle "for" en définissant exactement le rectangle à redessiner:
    //On redessine notre Carre
    int OFFSET = 1;
    pan.repaint(c.getPosX() - OFFSET, c.getPosY() - OFFSET,
            c.getLargeur() + OFFSET * 2, c.getHauteur() + OFFSET * 2);

} // fin du for

Ceci nous permet d'optimiser la méthode "paintComponent" en ne redessinant que ce qui est nécessaire, c.à d. ce qui chevauche le rectangle "clip". Par exemple, pour dessiner le fond blanc au début de la méthode "paintComponent":
Rectangle r = g.getClipBounds();
g.fillRect(r.x, r.y, r.width, r.height);
Messages postés
34
Date d'inscription
lundi 11 septembre 2006
Statut
Membre
Dernière intervention
19 février 2010

Merci d'avoir pris le temps de lire mon code Kertimanoff.
Pour les 'this', je trouve ça plus lisible de l'utiliser dans les constructeurs car parfois on se retrouve avec des lignes du genre nom nom et this.nom nom est plus compréhensible (le this.nom appartient à la classe et le nom est un paramètre du constructeur)

Pour le temps d'attente, c'est vrai. Mais je ne me suis pas penché là dessus ici :D
Messages postés
75
Date d'inscription
samedi 3 décembre 2005
Statut
Membre
Dernière intervention
30 juin 2013

il pourrait étre interraissant aussi de fair dépendre le temps d'attente Thread.sleep(x); en fonction du temps d'execution du reste du code. cela permettrai d'obtenir dans le meilleur des cas un déplacement "aussi rapide" des figures quelque soit la machine. bien qu'ici ce temps est négligeable, et ce n'est pas non plus le sujet. la lisibilité du code et les commentaires son apréciables. Merci
Afficher les 7 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.