IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Composants Java Discussion :

Problème d'animation sur un composant personnalisé


Sujet :

Composants Java

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2014
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2014
    Messages : 2
    Points : 1
    Points
    1
    Par défaut Problème d'animation sur un composant personnalisé
    Bonjour, je suis novice en java, et j'aurais besoin de vos lumières afin de m'éclairer sur la/les erreur(s) que j'ai pu faire.

    Objectif :


    Je souhaite créer un composant Goutte, qui me permet de faire l'animation d'une goutte d'eau qui tombe sur la surface de l'eau.
    Cette animation consiste à créer une série de cercles concentrique se propagent du centre vers l'extérieur du cercle.

    Code :

    Pour ce faire j'ai créer une classe Cercle qui permet de dessiner un cercle plein ou vide.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
     
    public class Cercle extends JPanel{
     
    	private int x;
    	private int y;
    	private int r;
    	private Color couleur;
    	private Boolean type; // true : cercle rempli | false :  cercle avec contour 
     
    	//constructeur de l'objet cercle
     
    	public Cercle(){
     
    	}
     
    	public Cercle(int x, int y, int r, Color couleur,boolean type){
    		this.x = x;
    		this.y = y;
    		this.r = r;
    		this.couleur = couleur;
    		this.type = type;
    	}
     
    	public void update(Graphics g){
    		paint(g);
    	}
     
    	//dessiner un cercle dans un contexte graphic
    	public void paint(Graphics g){   
    		Graphics2D g2 = (Graphics2D) g;
    		g2.setColor(couleur);			// on met la couleur 
    		if(type){
    			g2.fillOval(x-r, y-r, 2*r, 2*r);	// on dessine un cercle plein 
    		}else{
    			g2.drawOval(x-r, y-r, 2*r, 2*r);	// on dessine un cercle vide 
    		}
     
    	}
     
          //Getters et setters ... 
    }
    J'ai ensuite créer une classe Goutte qui me permet de faire mon animation. J'ai également mis un listener sur le clique de souris, afin d'ajouter à chaque clique, un cercle à ma liste de cercle de propagation. Le main permettant de lancer l'animation et aussi incluse dans la classe Goutte.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
     
    public class Goutte extends JComponent implements MouseListener {
     
     
    	private static final long serialVersionUID = 1L;
     
    	private int x;
    	private int y;
    	private int r;
    	private Color couleur;
     	private Cercle c1; 			//contour exterieur de la goutte
    	private ArrayList<Cercle> lst_cercle;	// liste des cercles de progation
    	private Cercle c3; 			// cercle qui permet d'effacer les précédents cercles déssinés  
     
    	private Thread t = null;
     
    	//constructeurs	
    	public Goutte(){
    		super();		
    	}
     
    	public Goutte(int x, int y, int r, Color couleur){
    		super();	
    		this.x= x;
    		this.y = y;
    		this.r = r;
    		this.c1 = new Cercle(x,y,r,Color.black,false);//contour exterieur de la goutte		
    		lst_cercle = new ArrayList<Cercle>();
    		lst_cercle.add(new Cercle(x,y,0,couleur,false));			
    		this.c3 = new Cercle(x,y,r,Color.white,true);
    		this.addMouseListener(this);
    	}
            //affichage des cercles
    	public void paint(Graphics g){		
    		c3.update(g);		//on commence par effacer
    		Iterator<Cercle> it = lst_cercle.iterator();
    		int i =0;
    		while(it.hasNext()){
    			System.out.println("aff cercle num : "+ i);
    			Cercle c = (Cercle) it.next();
    			c.update(g);	//on dessine les cercles
    			i++;
    		}
    		c1.update(g);		//on dessine le contour
    	}
     
    	//ajoute un cercle à la liste des cercles
    	public void ajouterCercle(){
    			this.getLst_cercle().add(new Cercle(x,y,0,couleur,false));
    			//on ne lance un nouveau thread que s'il n'existe pas encore ou s'il est terminé
    			if(t== null || t.getState()==Thread.State.TERMINATED){
    				t = new Thread(new Runnable() {
    				      public void run() {	
    				    	  affichageGoutte();
    				      }
    					});
    				t.start();	
    			}	
    	}
     
    	//affiche les cercles présent dans la liste et les supprime quand ils ont atteint leurs tailles max
    	public void affichageGoutte(){
    		System.out.println("affichage goute");
    			int i=0;						
    				while(!lst_cercle.isEmpty()){
    					Iterator<Cercle> it = lst_cercle.iterator();
    					i=0;
    					while(it.hasNext()){						
    						Cercle c = (Cercle) it.next();
    						if(c.getR() < r){//si la taille du cercle est inférieur à la taille de la goutte  
    							c.setR(c.getR()+1);		//modification du diamètre
    						}else{ //sinon on supprime le cercle de la liste
    							it.remove();
    							System.out.println("supprime de la liste le "+i+" elt");
    						}
    						i++;
    					}
    					this.repaint();//affichage des modifications
    					//attente
    					try {
    						Thread.sleep(250);
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    				}
     
    	}
     
    	@Override
    	public void mouseClicked(MouseEvent arg0) {
    		// TODO Auto-generated method stub		
    		System.out.println("Mouse Clicked");
    		ajouterCercle();		
    	}
     
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    			JFrame jf =new JFrame();			
    			Goutte gr = new Goutte(50,30,15,Color.red);
    			System.out.println("programme lancé");
    			jf.setSize(200, 200);			
     
    			jf.add(gr);
    			jf.setLocationRelativeTo(null);
    			jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    			jf.setVisible(true);
     
    	}
    Problème :

    Mon problème, c'est qu'une fois que mon premier cercle de propagation atteint la taille de ma goutte, je la supprime de ma liste (ligne 74 dans la Classe Goutte), et c'est alors que l'affichage de mes cercles de propagation s'arrête. Et Pourtant la console m'affiche que le traitement s'effectue bien.

    Si vous avez déjà rencontré ce problème, ou si vous avez une idée de la source du problème je vous en serais éternellement reconnaissant.

    De plus si selon vous il y a des aberrations d'un point de vue conception, ou si il y a des usages à respecter pour la création des composants graphiques, je suis également preneur.

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    Le problème vient du constructeur de Goutte :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public Goutte(int x, int y, int r, Color couleur){
           super();    
           this.x= x;
           this.y = y;
           this.r = r;
           this.c1 = new Cercle(x,y,r,Color.black,false);//contour exterieur de la goutte      
           lst_cercle = new ArrayList<Cercle>();
           lst_cercle.add(new Cercle(x,y,0,couleur,false));            
           this.c3 = new Cercle(x,y,r,Color.white,true);
           this.addMouseListener(this);
       }
    Tu ne stockes pas l'argument couleur dans la variable couleur de la classe. Du coup, tous les Cercle ajoutés lorsque tu cliques ont une couleur null. Donc le setColor(couleur) de la méthode paint() de Cercle ne fait rien (à part pour c3 et c1), donc le cercle s'affiche dans la dernier couleur affectée au contexte graphique, c'est à dire la couleur du cercle d'effacement, puisqu'on l'affiche systématiquement en premier. En résumé, tes cercles s'affichent, mais en blanc sur blanc, donc tu ne les vois pas. Tu es trompé par le fait que tu ajoutes un cercle au début (ligne que j'ai mise en rouge), avec la couleur passée en argument du constructeur de Goutte, et non la variable couleur de la classe Goutte, argument qui lui a bien une valeur, donc tu as un premier cercle qui s'affiche en rouge : tant qu'il est affiché, les cercles concentriques suivant sont affichés eux aussi en rouge (sauf le dernier, la bordule, qui lui a bien la couleur Color.BLACK). D'ailleurs, ce premier Cercle ne devrais pas être ajouté dans le constructeur, puisque c'est uniquement sur clic que tu devrais le faire.

    Sinon, problème majeur de ton programme : l'accès par 2 threads à la liste de cercles. Le thread d'animation qui parcourt cette liste, et supprime éventuellement des cercles, et l'EDT qui, par l'appel de mouseClicked(), en ajoute. Tu risques d'obtenir une ConcurrentModificationException, si le cercle est ajouté par un thread pendant le parcourt par l'autre. Pour l'éviter, utilises synchronized sur la liste, pour éviter l'accès concurrent par les 2 threads.

    Ensuite, essayes d'avoir des variables et des méthodes qui ont un nom significatif (getRayon() au lieu de getR(), par exemple), et de respecter pour le moins les conventions de nommage : tu y gagneras en clarté et lisibilité du code.

    Pour le reste, ce n'est pas très important, mais inutile que la classe Cercle soit un JPanel : on peut avoir une classe quelconque qui a une méthode paint(). Et autant déclarer la variable type de cercle du type primitif boolean au lieu de Boolean.

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2014
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2014
    Messages : 2
    Points : 1
    Points
    1
    Par défaut
    Super !

    C'était bien ça. Merci pour ta réponse.
    Comme convenu voici ma reconnaissance éternelle.

    J'ai encore deux petites questions :

    1. J'ai bien rajouter un verrou(bloc synchronized) sur lst_cercle dans affichageCercle. Afin d’empêcher l'accès concurrent à lst_cercle par l'affichage et l'ajout de cercle. Pour tester j'ai mis le verrou dans les deux fonctions et je me suis retrouver avec de l'interblocage. Dans mon cas je n'ai besoin du verrou dans l'une ou l'autre des fonctions. Mais dans le cas ou j'ai un 3ième thread qui a besoin d'accéder à la liste.
    Comment je fais pour synchroniser mes 3 threads sans interblocage?

    2. Étant donner que les attributs x, y, r, couleur sont présents dans Cercle et dans Goutte, est ce qu'il ne serait pas plus judicieux que Goutte hérite de Cercle ?

  4. #4
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    On "synchronise" sur des références : donc le nombre de thread n'influe pas sur la façon de synchroniser. Pour les problèmes d'interblocage, c'est surprenant dans ton contexte : indiques-nous ton code pour voir.

    Pour l'héritage ou non, il n'y a pas vraiment de traitement en commun entre les cercles et les gouttes, si ? Bon, on pourrait imaginer une abstraction commune, dont héritent les 2. Pour 3 ou 4 variables en commun, je vois pas trop l'intérêt de faire cette hiérarchie. Par contre, si la bordure de la goutte et le fond de la goutte étaient affichées par la goutte directement, et non par des cercles spéciaux, ça pourrait commencer à prendre du sens, d'avoir une abstraction qui dessine un cercle ou un disque quelconque. On aurait une classe "goutte" qui l'étend et une classe "cercle concentrique" qui l'étend aussi (cette classe devrait avoir elle même la logique de gestion du rayon qui grandit, au lieu que cela soit goutte qui s'en occupe : goutte ne servirait qu'à créer des cercles concentrique).

Discussions similaires

  1. [2008R2] [SSRS] Problème de layers sur le composant MAP
    Par Brazzia2t dans le forum SSRS
    Réponses: 4
    Dernier message: 05/01/2012, 15h28
  2. Réponses: 2
    Dernier message: 28/02/2011, 21h33
  3. Problème de paint avec un composant personnalisé
    Par yuuzhantar dans le forum AWT/Swing
    Réponses: 7
    Dernier message: 21/08/2009, 11h48
  4. problème de contrôle sur un composant redessiné
    Par daweed dans le forum AWT/Swing
    Réponses: 1
    Dernier message: 16/01/2008, 15h27
  5. Problème d'événements sur un composant TChart
    Par 3nTiC dans le forum C++Builder
    Réponses: 2
    Dernier message: 04/07/2006, 16h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo