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

 Java Discussion :

Autres questions de débutant : graphisme


Sujet :

Java

  1. #41
    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
    Si la méthode est public, le problème c'est le type de monpano.

    Si tu fais JPanel monpano = new Pano();, pour le compilateur monpano c'est un JPanel, et tu ne peux pas appeler la méthode A().
    Si tu fais Pano monpano = new Pano();, alors tu peux faire monpano.A()Dans le premier cas, tu peux caster :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    JPanel monpano = new Pano();
    ((Pano)monpano).A();
    Avec le cast, tu dis au compilateur : je sais que monpano, c'est du Pano, alors tu peux appeler la méthode A(). bien sûr, si c'est faux à l'exécution, tu auras une erreur (ClassCastException).
    Et évidemment, il vaut mieux écrire dans ton cas Pano monpano. JPanel monpano c'est si tu n'as pas l'intention d'appeler des méthodes spécifiques, ou pour une méthode de traitement générique (par exemple, une méthode qui traite une liste de JPanel pour en changer la couleur).
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  2. #42
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2016
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2016
    Messages : 85
    Points : 20
    Points
    20
    Par défaut
    encore une fois, merci ! J'ai fait le cast et donc je peux traiter le texte de gauche dans le paint du panneau de droite. Je crois que j'ai compris des trucs importants...

  3. #43
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2016
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2016
    Messages : 85
    Points : 20
    Points
    20
    Par défaut
    Bonjour !

    j'ai un petit soucis : j'ai créé un jbutton et lui ai appliqué la méthode addActionListener et définit actionperformed qui fait un print et ça fait pas de print quand j'appuie sur le bouton. Qu'est ce qui est mal écrit ? SVP ?



    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
    class Fenetre extends JPanel {
    	private static final long serialVersionUID = 1L;	
    	Disque disque = new Disque(100,100,30,Color.RED) ;
    	private int flag_debut = 1 ;
     
    	Fenetre() {
    		JButton change_effect = new JButton("Déplacer/Modifier") ;
     
    		change_effect.addActionListener(new ActionListener() {
     
    			public void actionPerformed(ActionEvent e) {
    				System.out.println("Touché bouton") ;
    				// TODO Auto-generated method stub
     
    			}
     
    		});  
     
    		setLayout(new BorderLayout());
    		add(change_effect,BorderLayout.SOUTH) ;
     
    		addMouseMotionListener (new MouseAdapter() {
    			int oldX,oldY ;
     
    			public void mouseDragged(MouseEvent e) {
    			 if (disque.estdedans(e.getX(),e.getY())) {
    	           if ((e.getX() > oldX) || (e.getY()) > oldY) {

  4. #44
    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
    Je ne vois de problème dans ce que tu fais avec le bouton change_effect. Le message devrait bien s'afficher en console lorsqu'on actionne le bouton. Le problème vient alors d'autre chose, mais je n'ai pas le code complet.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  5. #45
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2016
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2016
    Messages : 85
    Points : 20
    Points
    20
    Par défaut
    je crois que j'ai trouvé ...

  6. #46
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2016
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2016
    Messages : 85
    Points : 20
    Points
    20
    Par défaut
    Sinon j'ai fait ce petit jeu ou il faut détruire des ballons en cliquant dessus.
    Quand la souris bouge dans la frame, le déplacement des ronds est fluide, mais dès que la souris est à l'extérieur, c'est sacadé.

    Tu sais pourquoi ?

    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
    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
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    package jeudisques;
     
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.FlowLayout;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.util.ArrayList;
    import java.util.Random;
    import java.util.Timer;
    import java.util.TimerTask;
     
    import javax.swing.JColorChooser;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
     
     
     
    class Fenetre extends JPanel  {
    	private Color couleurdefond ;
    	private ArrayList<Disque> mesdisques ;
    	private int tempo_disque = 0 ; // pour empecher d'avoir des nouveaux ballons trop vite et permettre le montée rapide des ballons
    	Fenetre(Color couleur,final ArrayList<Disque> mesdisques) {
    		this.couleurdefond = couleur ;
    		this.mesdisques = mesdisques ;
    		setLayout(new FlowLayout());
    		setBackground(couleur) ;
    		addMouseMotionListener (new MouseAdapter() {
    			int oldX,oldY ;
     
    			public void mouseDragged(MouseEvent e) {
     
    			}
    			public void mouseMoved(MouseEvent e) {
     
    			}
     
    		});
     
     
    		addMouseListener(new MouseAdapter() { 
    	          public void mousePressed(MouseEvent e) { 
    	            //System.out.println("Mousse Pressed "+e.getX()+" "+e.getY()); 
    	          } 
     
    	          public void mouseClicked(MouseEvent e) {
    	        	 Disque disque_destroyed = null ;
    	        	 for (Disque disque : mesdisques) {
     
    					int x = disque.getX(); int y = disque.getY();
     
    					if (disque.estdedans(e.getX(),e.getY())) {
    					    disque_destroyed = disque ;
    						mesdisques.remove(disque) ;
    						//System.out.println("Est dedans"+ disk_destroyed.getX()); 
    						break ;
    		        	}
    					else {
     
    					}
     
    	        	 } 
    	        	 if (disque_destroyed != null) {
    	               Graphics g = getGraphics() ; 
    	               int x = disque_destroyed.getX() ;	int y = disque_destroyed.getY() ; int diametre = disque_destroyed.getDiametre() ;
    	               int rc = disque_destroyed.getRcouleur();int gc = disque_destroyed.getGcouleur();int bc = disque_destroyed.getBcouleur();
    	               g.setColor(new Color(255-rc,255-gc,255-bc)) ;
    	               g.fillOval(x-diametre/2, y-diametre/2, 2*diametre, 2*diametre) ; }
    	      	  }
     
     
    	    	  public void mouseReleased(MouseEvent e) {
    	    		  //System.out.println("Mousse Released "+e.getX()+" "+e.getY()); 
    	    		// TODO Auto-generated method stub
     
    	    	  }
     
    	    	  public void mouseEntered(MouseEvent e) {
    	    		  //System.out.println("Mousse Entered "+e.getX()+" "+e.getY()); 
    	    		// TODO Auto-generated method stub
    	    	  }
    	    	  public void mouseExited(MouseEvent e) {
    	    		  //System.out.println("Mousse Exited "+e.getX()+" "+e.getY()); 
    	    			// TODO Auto-generated method stub
     
    	          }
    	        }); 
    	}
     
    	public void paint(Graphics g) {
     
    		 final int width=getWidth();
    		 final int height=getHeight();
    	     Random randomno = new Random();
    		 int diametre = randomno.nextInt(70);
    		 int abscisse = randomno.nextInt(width-diametre);
    		 int ordonnee = height-diametre ;
    		 int rcolor = randomno.nextInt(255);
    		 int gcolor = randomno.nextInt(255);
    		 int bcolor = randomno.nextInt(255);
    		 super.paint(g);
    		 if ( tempo_disque == 0 ) {
    			    Disque disque = new Disque(abscisse,ordonnee,diametre,rcolor,gcolor,bcolor,g) ;
    			    mesdisques.add(disque);
    			 }
    		 if ( tempo_disque == 25 ) {
    			tempo_disque = 0 ;
    		    Disque disque = new Disque(abscisse,ordonnee,diametre,rcolor,gcolor,bcolor,g) ;
    		    mesdisques.add(disque);
    		 }
    		 tempo_disque+=1 ;
    		 for (Disque mondisque : mesdisques) {
    			 int oldY = mondisque.getY() ;
    			 oldY-=1 ;
    			 mondisque.setY(oldY) ;
    			 mondisque.Afficher(g) ;
    		 }
     
    	}
    }
     
    class Disque {
    	private int XO,YO,diam,rC,gC,bC ;
    	private Graphics g ;
    	private Color Couleur ;
    	Disque(int XO,int YO,int diam,int rC,int gC,int bC,Graphics g) {
    		this.XO = XO ;this.YO = YO ;this.diam = diam ;this.rC = rC ;this.gC = gC ;this.bC = bC ;
    	}
    	void Afficher(Graphics g) {
    		g.setColor(new Color(this.rC,this.gC,this.bC)) ;
    		g.fillOval(this.XO, this.YO, this.diam, this.diam) ;
    		//g.setColor(Color.BLACK) ;
    		//g.drawRect(this.XO, this.YO, this.diam, this.diam) ;
    	}
    	void Afficher(Graphics g,Color Couleur) {
    		g.setColor(Couleur) ;
    		g.fillOval(this.XO, this.YO, this.diam, this.diam) ;
    		//g.setColor(Color.BLACK) ;
    		//g.drawRect(this.XO, this.YO, this.diam, this.diam) ;
    	}
    	public boolean estdedans (int x,int y) {
    		//System.out.println("est dedans "+x+" "+this.x+" "+y+" "+this.y) ;
    		if (((x>=this.XO) && (x<= this.XO+diam)) && ((y>=this.YO)&&(y<=this.YO+diam))) {
    			//System.out.println("est dedans ") ;
    			return true ;
    		}
    		else return false ;
    	}
    	int getDiametre() {
    		return this.diam ;
    	}
    	void setDiametre(int diametre) {
    		this.diam = diametre ;	
    	}
    	int getX() {
    		return this.XO ;
    	}
    	int getY() {
    		return this.YO ;
    	}
    	void setPosition(int x,int y) {
    		this.XO = x ; this.YO = y ;
    	}
    	void setX(int x) {
    		this.XO = x ;
    	}
    	void setY(int y) {
    	    this.YO = y ;
    	}
    	void setCouleur(int r,int g,int b) {
    		this.rC = r ;
    		this.gC = g ;
    		this.bC = b ;
    	}
        int getRcouleur() { return this.rC ;}
        int getGcouleur() { return this.gC ;}
        int getBcouleur() { return this.bC ;}
    }
    public class JeuDisques {
     
    	public static void main(String[] args) {
    		ArrayList<Disque> mesdisques = new ArrayList<Disque>() ;
    		long temps = 50 ;                      // délai avant de répéter la tache : 2000 = 2  seconde
    	    long startTime = 0;                    // délai avant la mise en route (0 demarre immediatement)
    	    Timer timer = new Timer();             // création du timer
    		Color couleur = Color.WHITE ;
    		JFrame frame = new JFrame("Disques Aléatoires");
    		final JPanel panel = new Fenetre(couleur,mesdisques) ;
     
    		frame.add(panel) ;
    		TimerTask tache = new TimerTask() {     // création et spécification de la tache à effectuer
    	         @Override
    	         public void run() {
    	        	panel.repaint() ;
     
    	         }
    	     };
    	    timer.scheduleAtFixedRate(tache,startTime,temps);  // ici on lance la mecanique
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		frame.setLocation(200, 200);
    		frame.setSize(600,400);
    		frame.setResizable(true) ;
    		frame.setVisible(true);
     
    	}
    }

  7. #47
    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
    Je ne constate pas de saccades. Il se peut que ça vienne de ton environnement. Néanmoins, 2 ou 3 choses :

    1. Je t'ai déjà dit d'en faire le minimum dans le thread graphique. Tu ne dois pas faire le mouvement (la décrémentation des Y dans la méthode paint). Tu ne dois pas ajouter des disques dans la liste non plus dans cette méthode, ou en retirer. Déjà, ta vitesse d'animation dépend de ton taux de rafraichissement graphique. Mais en plus, ça bloque le thread graphique pendant un moment "long", ce qui pourrait expliquer les saccades que tu observes dans certaines conditions. Sans compter que tu fais plein de chose inutilement (peu coûteuses certes, mais quand même).
      Instancier des classes peut être également couteûx. Quand ce n'est pas indispensable, l'éviter : par exemple utiliser ThreadLocalRandom au lieu de créer un Random dans paint().
    2. Il y a quelque part un problème dans la sélection des ballons (parfois, on a beau cliquer dessus, il ne se passe rien), et je pense que c'est dû à tout ça (à chaque cycle d'animation, on a un décalage entre les coordonnées visibles et celles clickables. Le fait d'utilise clicked() y contribue (plutôt utiliser pressed je pense)
    3. Je t'ai déjà dit de ne pas utiliser la méthode getGraphics(). Change l'état de ce qu'il y a à dessiner, et fait un repaint(). Le mieux étant de gérer une file évenementielle commune au déplacement et à la desctruction, qui elle fait un seul repaint().
    4. Pense qu'au bout d'un certain temps, tu auras des dizaines, puis des centaines, puis des milliers (on ne sait jamais, un passioné qui jouerait pendant des heures) de balons dans ta listes, dont la plupart ne serait pas affiché, mais quand même traité (y compris dans le MouseListener). Bien sûr, sur la plupart des machines modernes, le parcourt de la liste est extrêment rapide, même avec des centaines de balons dedans, mais le moindre délai dans l'affichage, peut causer des effets de saccades. Pour peu que le système prenne la main pour faire autre chose, et on a également un effet de saccade.
    5. Il existe des effets inhérents au défilement animé de zone d'écran qui causent des effets s'apparentant aux saccades (on appelle ça "flckering"). Le problème vient du fait qu'on commence à dessiner (donc à effacer) une zone qui est en cours de dessin. On évite ça avec une technique dite de multi-buffering.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  8. #48
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2016
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2016
    Messages : 85
    Points : 20
    Points
    20
    Par défaut
    merci pour tes remarques ...
    mais qu'est ce que je fais inutilement, que ce soit maldroit OK, mais inutile, ça mérite d'etre corrigé.
    J'ai repris un script que tu avais modifié, une méthode anim qui est appelée dans le run au lieu de repaint(). Mais j'ai un getWidth et getHeight qui me ramène 0, alors que la fenetre est sizée. J'ai déplacé le frame.setSize mais je n'arrive pas à avoir autre chose que 0.
    Voici le script :

    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
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    package disquesaleatoires;
     
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.FlowLayout;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.util.ArrayList;
    import java.util.Random;
    import java.util.Timer;
    import java.util.TimerTask;
    import java.util.concurrent.ThreadLocalRandom;
     
    import javax.swing.JColorChooser;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
     
    class Fenetre extends JPanel  {
    	private Color couleurdefond ;
    	private ArrayList<Disque> mesdisques ;
    	Fenetre(Color couleur,final ArrayList<Disque> mesdisques) {
    		this.couleurdefond = couleur ;
    		this.mesdisques = mesdisques ;
     
    		setLayout(new FlowLayout());
    		setBackground(couleur) ;
     
    		addMouseListener(new MouseAdapter() {
     
    			@Override
    			public void mouseClicked(MouseEvent e) {
    				 final int width=getWidth();
    				 final int height=getHeight();
    			     Random randomno = new Random();
    				 int diametre = randomno.nextInt(Math.min(Math.min(width, height),150));
    				 int abscisse = e.getX()-diametre/2;
    				 int ordonnee = e.getY()-diametre/2;
    				 int rcolor = randomno.nextInt(255);
    				 int gcolor = randomno.nextInt(255);
    				 int bcolor = randomno.nextInt(255);
    				 Disque disque = new Disque(abscisse,ordonnee,diametre,rcolor,gcolor,bcolor) ;
    				 mesdisques.add(disque);
    				 repaint();
    			}
     
    		});
    	}
    	public void paint(Graphics g) {
     
    		 super.paint(g);
    		 for (Disque mondisque : mesdisques) {
    			 mondisque.Afficher(g) ;
    		 }
     
    	}
    	public void anim() {
    		 final int width=getWidth();
    		 final int height=getHeight();
    		 System.out.println("Ajout disque "+width+" "+ height) ;
    		 int diametre = ThreadLocalRandom.current().nextInt(50) ;
    		 int abscisse = ThreadLocalRandom.current().nextInt(width-diametre) ;
    		 int ordonnee = ThreadLocalRandom.current().nextInt(height-diametre) ;
    		 int rcolor = ThreadLocalRandom.current().nextInt(255) ;
    		 int gcolor = ThreadLocalRandom.current().nextInt(255) ;
    		 int bcolor = ThreadLocalRandom.current().nextInt(255) ;
    		 Disque disque = new Disque(abscisse,ordonnee,diametre,rcolor,gcolor,bcolor) ;
    		 mesdisques.add(disque);
    		 System.out.println("Ajout disque "+abscisse) ;
    		 for (Disque mondisque : mesdisques) {
    			 int olddiam = mondisque.getDiametre() ;
    			 olddiam+=1 ;
    			 mondisque.setDiametre(olddiam) ;
    		 }
    		 repaint();
    	}
    }
     
    class Disque {
    	private int XO,YO,diam,rC,gC,bC ;
    	Disque(int XO,int YO,int diam,int rC,int gC,int bC) {
    		this.XO = XO ;this.YO = YO ;this.diam = diam ;this.rC = rC ;this.gC = gC ;this.bC = bC ;
    		//g.setColor(new Color(rC,gC,bC)) ;
    		//g.fillOval(XO, YO, diam, diam) ;
    		//g.dispose() ; 
    	}
    	void Afficher(Graphics g) {
    		g.setColor(new Color(this.rC,this.gC,this.bC)) ;
    		g.fillOval(this.XO, this.YO, this.diam, this.diam) ;
    		//g.dispose() ; 
    	}
    	int getDiametre() {
    		return this.diam ;
    	}
    	void setDiametre(int diametre) {
    		this.diam = diametre ;	
    	}
    }
    public class DisquesAleatoires {
     
    	public static void main(String[] args) {
    		ArrayList<Disque> mesdisques = new ArrayList<Disque>() ;
    		long temps = 2000;                      // délai avant de répéter la tache : 2000 = 2  seconde
    	    long startTime = 0;                    // délai avant la mise en route (0 demarre immediatement)
    	    Timer timer = new Timer();             // création du timer
    		Color couleur = Color.WHITE ;
    		JFrame frame = new JFrame("Disques Aléatoires");
    		frame.setSize(600,400);
    		final Fenetre panel = new Fenetre(couleur,mesdisques) ;
     
    		frame.add(panel) ;
     
    		TimerTask tache = new TimerTask() {     // création et spécification de la tache à effectuer
    	         @Override
    	         public void run() {
    	        	panel.anim() ;
     
    	         }
    	     };
    	    timer.scheduleAtFixedRate(tache,startTime,temps);  // ici on lance la mecanique
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		frame.setLocation(200, 200);
     
    		frame.setResizable(true) ;
    		frame.setVisible(true);
     
    	}
    }

  9. #49
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2016
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2016
    Messages : 85
    Points : 20
    Points
    20
    Par défaut
    j'ai trouvé des trucs inutiles, et j'ai corrigé pas mal de trucs voici

    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
    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
    package disquesaleatoires;
     
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.FlowLayout;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.util.ArrayList;
    import java.util.Random;
    import java.util.Timer;
    import java.util.TimerTask;
    import java.util.concurrent.ThreadLocalRandom;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
     
     
     
     
     
    class Fenetre extends JPanel  {
    	private Color couleurdefond ;
    	private ArrayList<Disque> mesdisques ;
    	private int tempo_disque = 0 ; // pour empecher d'avoir des nouveaux ballons trop vite et permettre le montée rapide des ballons
    	Fenetre(Color couleur,final ArrayList<Disque> mesdisques) {
    		this.couleurdefond = couleur ;
    		this.mesdisques = mesdisques ;
     
    		setLayout(new FlowLayout());
    		setBackground(couleur) ;
     
    		addMouseListener(new MouseAdapter() {
     
    			@Override
    			public void mouseClicked(MouseEvent e) {
     
    			}
    			public void mousePressed(MouseEvent e) {
    				for (Disque disque : mesdisques) {
     
    					int x = disque.getX(); int y = disque.getY();
     
    					if (disque.estdedans(e.getX(),e.getY())) {
     
    						mesdisques.remove(disque) ;
    						//System.out.println("Est dedans"+ disk_destroyed.getX()); 
    						break ;
    		        	}
    					else {
     
    					}
     
    	        	 } 
    			}
     
    		});
    	}
    	public void paint(Graphics g) {
     
    		 super.paint(g);
    		 for (Disque mondisque : mesdisques) {
    			 mondisque.Afficher(g) ;
    		 }
     
    	}
    	public void anim() {
    		 final int width=600;//getWidth();
    		 final int height=400;//getHeight();
    		 //System.out.println("Ajout disque "+width+" "+ height) ;
     
    		 if ( (tempo_disque == 0) || (tempo_disque == 25) ) {
    			 if ( tempo_disque == 25 ) tempo_disque = 0 ;
    			 int diametre = ThreadLocalRandom.current().nextInt(100) ;
    			 int abscisse = ThreadLocalRandom.current().nextInt(width-diametre) ;
    			 int ordonnee = height -50 ;
    			 int rcolor = ThreadLocalRandom.current().nextInt(255) ;
    			 int gcolor = ThreadLocalRandom.current().nextInt(255) ;
    			 int bcolor = ThreadLocalRandom.current().nextInt(255) ;
    			 Disque disque = new Disque(abscisse,ordonnee,diametre,rcolor,gcolor,bcolor) ;
    			 mesdisques.add(disque);
    		 }
     
    		 tempo_disque+=1 ;
    		 for (Disque mondisque : mesdisques) {
     
    			 mondisque.setY(mondisque.getY() -1 );
     
    		 }
    		 repaint();
    	}
    }
     
    class Disque {
    	private int XO,YO,diam,rC,gC,bC ;
    	Disque(int XO,int YO,int diam,int rC,int gC,int bC) {
    		this.XO = XO ;this.YO = YO ;this.diam = diam ;this.rC = rC ;this.gC = gC ;this.bC = bC ;
    		//g.setColor(new Color(rC,gC,bC)) ;
    		//g.fillOval(XO, YO, diam, diam) ;
    		//g.dispose() ; 
    	}
    	void Afficher(Graphics g) {
    		g.setColor(new Color(this.rC,this.gC,this.bC)) ;
    		g.fillOval(this.XO, this.YO, this.diam, this.diam) ;
    		//g.dispose() ; 
    	}
    	int getDiametre() {
    		return this.diam ;
    	}
    	void setDiametre(int diametre) {
    		this.diam = diametre ;	
    	}
    	int getX() {
    		return this.XO ;
    	}
    	int getY() {
    		return this.YO ;
    	}
    	void setX(int x) {
    		this.XO = x ;
    	}
    	void setY(int y) {
    	    this.YO = y ;
    	}
    	void setPosition(int x,int y) {
    		this.XO = x ; this.YO = y ;
    	}
    	public boolean estdedans (int x,int y) {
    		//System.out.println("est dedans "+x+" "+this.x+" "+y+" "+this.y) ;
    		if (((x>=this.XO) && (x<= this.XO+diam)) && ((y>=this.YO)&&(y<=this.YO+diam))) {
    			//System.out.println("est dedans ") ;
    			return true ;
    		}
    		else return false ;
    	}
    }
    public class DisquesAleatoires {
     
    	public static void main(String[] args) {
    		ArrayList<Disque> mesdisques = new ArrayList<Disque>() ;
    		long temps = 50;                      // délai avant de répéter la tache : 2000 = 2  seconde
    	    long startTime = 0;                    // délai avant la mise en route (0 demarre immediatement)
    	    Timer timer = new Timer();             // création du timer
    		Color couleur = Color.WHITE ;
    		JFrame frame = new JFrame("Disques Aléatoires");
    		frame.setSize(600,400);
    		final Fenetre panel = new Fenetre(couleur,mesdisques) ;
     
    		frame.add(panel) ;
     
    		TimerTask tache = new TimerTask() {     // création et spécification de la tache à effectuer
    	         @Override
    	         public void run() {
    	        	panel.anim() ;
     
    	         }
    	     };
    	    timer.scheduleAtFixedRate(tache,startTime,temps);  // ici on lance la mecanique
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		frame.setLocation(200, 200);
     
    		frame.setResizable(true) ;
    		frame.setVisible(true);
     
    	}
    }
    je vais compliquer le jeu, mais chez moi ç'est tjrs sacadé si la souris est immobile...

  10. #50
    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
    Citation Envoyé par SeniorEric Voir le message
    merci pour tes remarques ...
    mais qu'est ce que je fais inutilement, que ce soit maldroit OK, mais inutile, ça mérite d'etre corrigé.
    Ce dont je parlais quand je parlais de code inutile c'est ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     Random randomno = new Random();
    		 int diametre = randomno.nextInt(70);
    		 int abscisse = randomno.nextInt(width-diametre);
    		 int ordonnee = height-diametre ;
    		 int rcolor = randomno.nextInt(255);
    		 int gcolor = randomno.nextInt(255);
    		 int bcolor = randomno.nextInt(255);
    Tout ce que tu calcules/définis dans ce bloc est utilisé que dans 2 cas : si tempo_disque vaut 0 et si tempo_disque vaut 25. Il y a donc tous les autres cas (24 cas) où tous ces calculs (qui prennent des ressources (du temps cpu, de la mémoire) sont faits inutilement (bien sûr ça peut prendre quelques millisecondes, donc peanuts, mais dans un process qui a besoin de rafraichir rapidement la GUI, ça peut donner des effets de saccades). Soit ne le faire que si tempo_disque vaut 0 ou 25, soit le faire dans un autre thread qui n'aura pas d'influence direc sur le thread graphique (le seul risque qu'on ait, c'est que le rafraichissement ne se fasse pas au moment où on veut : au pire, on va perdre des frames). Après, il y a d'autres techniques plus compliquées pour éviter de perdre les étapes d'animation sur le timer (parce que ça peut aussi arriver) : dans ton cas, il faudrait calculer la position du ballon non pas par incrémentation, mais par différence avec la position de départ et d'arrivée, en relation avec le temps écoulé depuis le départ. Dans ton petit programme, on peut se contenter de ne pas aller jusque là, et admettre que, tant pis, si un process se déclenche et empêche le process de faire monter les disques de monter pendant 50 ms, tu auras une/des saccade/s.

    Citation Envoyé par SeniorEric Voir le message
    J'ai repris un script que tu avais modifié, une méthode anim qui est appelée dans le run au lieu de repaint(). Mais j'ai un getWidth et getHeight qui me ramène 0, alors que la fenetre est sizée. J'ai déplacé le frame.setSize mais je n'arrive pas à avoir autre chose que 0.
    Tu lances ton animation avant d'afficher la fenêtre. Tant que la fenêtre n'a pas été affichée, les composants qu'on lui a ajouté n'ont pas encore été layoutés (comprendre : positionnés et dimensionnés). Donc, il font une taille arbitraire qui n'a pas encore été calculée et un JPanel fait 0x0 avant tout layout. C'est pour ça que je démarrais mon animation dans le windowOpened de WindowAdapter dans mes premiers exemples : pour être sûr que mon animation commence bien lorsque la fenêtre est vraiment affichée, et donc, que le JPanel a bien (déjà) une taille. Maintenant, ce n'est la plupart du temps pas très grave, sauf si on divise par l'une des dimensions (erreur division par 0), et, bien sûr si on veut générer des trucs qui dépendent de la taille. Si on ne fait que redessiner, on va redessiner un coup pour rien (puisque pas affiché) : ce n'est pas très important/grave (et c'est pour ça que j'ai laissé ensuite tes codes dans le WindowAdapter) : les petites pertes de temps ne sont réellement gênantes que lorsqu'elles sont répétées. Maintenant que tu génères un disque dans anim(), tu as intérêt à ne pas lancer l'animation avant que la fenêtre soit affichée, sinon ça va générer des disques de diamètres nuls. Autre façon de t'en sortir : le process de génération devrait être indépendant du processus d'animation : l'animation c'est uniquement faire monter les ballons vers le haut (et les faire disparaitre lorsqu'ils sortent de l'écran = les retirer de la liste). Avec un autre process, lui démarrer lorsque la fenêtre est affichée, tu généras des disques au bon moment. En fait, tu as déjà essayé de contourner ça en introduisant ta variable tempo_disque : tu as cherché a simuler un autre timer avec une variable qui s'incrémente et dont tu testes des valeurs particulières (0 et 25), et que tu remets à 0 lorsque ça dépasse 25. Avec 2 timers, tu as des codes indépendant. Cependant, ça introduit une complexité supplémentaire : tu vas devoir gérer l'accès concurrent entre les 2, mais comme de toute manière tu dois le faire aussi avec qu'un seul (parce que de toute manière, tu as bien déjà 2 threads qui accèdent à la liste de disques : l'EDT, qui parcourt la liste de disques et le timer qui la modifie).
    Sauf, bien sûr, si tu peux absolument générer un ballon à chaque tick d'animation : dans ce cas, soit démarrer donc l'anim quand la fenêtre est affichée, soit tester si elle l'est lors de la génération, mais ça oblige à tester la visibilité de la fenêtre alors que l'animation concerne le panel : on risque que la fenêtre dise qu'elle est affichée alors que le panel ne l'est pas. Tester le isVisible() du panel pourrait être la solution, mais il peut répondre true alors qu'il n'est pas visible dans de rares cas de layout (isVisible d'un composant veut dire qu'on a dit qu'on voulait qu'il le soit, pas qu'il l'est réellement).
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  11. #51
    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
    Citation Envoyé par SeniorEric Voir le message
    je vais compliquer le jeu, mais chez moi ç'est tjrs sacadé si la souris est immobile...
    Il faut alors peut être envisager de mettre en place une technique de double-buffering. Globalement, c'est simple (seulement, il faut absolument démarrer lorsque le composant est affiché, sinon erreur). Il y a un exemple que j'avais fait il y a un bail ici. Si j'ai le temps, je modifierai le code que tu me montres pour y introduire le double-buffering.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  12. #52
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2016
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2016
    Messages : 85
    Points : 20
    Points
    20
    Par défaut
    J'aimerais bien en plus du double buffering, utiliser les threads. Pour avoir en effet un thread qui génère les ballons et un autre qui les fait monter par exemple. Et utiliser le sleep ou wait je ne sais plus du thread pour gérer tout ça.
    Edit : à bon, j'ai déjà 2 thread ?

  13. #53
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2016
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2016
    Messages : 85
    Points : 20
    Points
    20
    Par défaut
    J'ai fait un exo sur les threads où il faut faire un chronometre graphique ; afficher un secteur de disque qui augmente avec le temps. J'ai juste 2 choses à dire :
    1 l'affichage est tjrs sacadé si je laisse la souris immobile alors que là le code est plutot simple
    2 j'ai une question sur la vie des threads ; dans le programme il y a un bouton pour démarrer le chrono, un pour suspendre, reprendre et stopper.
    Une fois qu'il est stoppé, donc aprés la méthode stop ( qui est deprecated d'ailleurs ) comment on peut le tester pour savoir si on peut en créer un autre en appuyant sur démarrer ?
    Ou bien, une fois qu'on a fait stop, comment redémarrer sans relancer le programme ?

    Voici le code en 3 parties.

    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
    package chrono;
     
    import java.awt.Color;
    import java.awt.Graphics;
     
    import javax.swing.JComponent;
     
    public class Chrono implements Runnable {
    	private int x, y, diametre;
    	private JComponent proprietaire;
    	private Thread deroulement;
    	private long tempsEcoule = 0; // exprime en millisecondes
    	private long duree; // nombre de millisecondes pour un tour complet
     
    	/* - proprietaire donne le composant devant contenir l'image du chronometre.
    	 * - duree donne le temps en secondes mis pour que le chronometre fasse un tour complet,
    	 * apres ce temps, le chronometre s'arrete.
    	 * - x et y indiquent  les coordonnees du coin superieur gauche du carre 
    	 * circonscrit au chronometre
    	 *- diametre indique le diametre du chronometre*/
    	public Chrono(JComponent proprietaire, int duree, 	int x, int y, int diametre) {
    		this.duree = duree * 1000;
    		this.x = x;
    		this.y = y;
    		this.diametre = diametre;
    		this.proprietaire = proprietaire;
    	}
     
    	/* Demarre le chronometre */
    	public void demarrer()  { 
    		if (deroulement==null) {
    		   tempsEcoule = 0 ;
    		   deroulement = new Thread(this) ;
    		   deroulement.start();
    		}
    		else proprietaire.repaint();
    	}
     
    	/* Suspend le deroulement du temps ; ce deroulement pourra etre repris 
    	 * dans l'etat ou il se trouvait par la methode reprendre */
    	public void suspendre() {   
    		if (deroulement==null) return ;
    		if (deroulement.isAlive()) deroulement.suspend();
    	}
     
    	/* Si le chronometre est en fonctionnment mais a ete suspendu, 
    	 * il recommence a tourne r*/ 
    	public synchronized  void reprendre() {
    		if (deroulement==null) return ;
    		if (deroulement.isAlive()) deroulement.resume();
    		//A COMPLETER
    	}
     
    	/* Arrete le chronometre. Une fois arrete, le chronometre ne peut
        repartir qu'avec la methode demarrer, au debut du d�compte du temps*/
    	@SuppressWarnings("deprecation")
    	public synchronized void arreter() {
    		if (deroulement==null) return ;
    		if (deroulement.isAlive()) 
    			{ deroulement.stop(); tempsEcoule = 0 ; 
    			  //proprietaire.repaint() ;
    			}
    	}
     
    	/* Fait tourner le chronometre */
    	public void run() {
    		while (tempsEcoule<duree) {
    		try {
    			deroulement.sleep(100);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		//System.out.println("Hello from RUN!"+tempsEcoule+" "+duree);
    		tempsEcoule+=100 ;
    		proprietaire.repaint() ;
    		}
     
    	}
     
    	/* Retourne true si le chronometre est en fonctionnement,  eventuellement suspendu 
    	 * et false si le chronometre n'est pas demarre, ou bien a ete arrete, ou bien a fini de tourner*/
    	public boolean enFonctionnement() {
    		if (deroulement.isAlive()) return true ;
    		else return false ;
    	}
     
    	/* Dessine le chronometre selon le temps pendant lequel il a tourne  depuis qu'il a ete mis en fonctionnement */
    	public void dessine(Graphics g) {
    		//System.out.println("Hello from dessine! "+tempsEcoule+" "+duree);
    		g.setColor(Color.YELLOW);
    		g.fillArc(x, y, diametre, diametre, 90,
    				(int)(360 - tempsEcoule * 360 / duree));
    		g.setColor(Color.GREEN);
    		g.fillArc(x, y, diametre, diametre,90,
    				(int)(-tempsEcoule * 360 / duree));
    		g.setColor(Color.RED) ;
    		String strtemps = " "+ tempsEcoule ;
    		g.drawString(strtemps, 100, 270) ;
    	}
    }
    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
    package chrono;
     
    import java.awt.Dimension;
    import java.awt.FlowLayout;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
     
    import javax.swing.JButton;
    import javax.swing.JPanel;
     
     
    public class IHMChrono extends JPanel implements ActionListener {
    	private static final long serialVersionUID = 1L;
     
    	JButton demarrer = new JButton("demarrer");
    	JButton suspendre = new JButton("suspendre");
    	JButton reprendre = new JButton("reprendre");
    	JButton arreter = new JButton("arreter");
    	Chrono chrono;
     
    	public IHMChrono(int duree) {
    		setPreferredSize(new Dimension(500,300));
    		setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10));
    		chrono = new Chrono(this, duree, 200, 120, 100);
    		demarrer.addActionListener(this);
    		suspendre.addActionListener(this);
    		reprendre.addActionListener(this);
    		arreter.addActionListener(this);
    		add(demarrer);
    		add(suspendre);
    		add(reprendre);
    		add(arreter);
    		setVisible(true);
    	}
     
    	public void actionPerformed(ActionEvent evt) {
    		Object source = evt.getSource();
     
    		if (source == demarrer) chrono.demarrer();
    		else if  (source == suspendre) chrono.suspendre();
    		else if  (source == reprendre) chrono.reprendre();
    		else if  (source == arreter) chrono.arreter();
    	}
     
    	public void paintComponent(Graphics g)  {
    		super.paintComponent(g);
    		chrono.dessine(g);
    	}
    }
    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
    package chrono;
     
    import javax.swing.JFrame;
     
     
    public class AppliChrono {
    	  public static void main(String[] argv) {   
    	      JFrame fenetre = new JFrame();
    	      //fenetre.setContentPane(new IHMChrono(Integer.parseInt(argv[0])));
    	      fenetre.setContentPane(new IHMChrono(60));
    	      fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    	      fenetre.setLocation(100, 100);
    	      fenetre.pack();
    	      fenetre.setVisible(true);
    	    }
    	}
    Merci d'avance

    et aussi est ce identique d'implémentar runnable et d'étendre Thread ?

  14. #54
    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
    Citation Envoyé par SeniorEric Voir le message
    1 l'affichage est tjrs sacadé si je laisse la souris immobile alors que là le code est plutot simple
    Une raison pour ces saccades est le fait que tu as une animation à 10 images par secondes. L'œil et le cerveau (=la vue) humain moyen ne perçoit le mouvement qu'à partir de 25 à 30 images par secondes. Moins on a d'images par secondes, plus le mouvement perd en fluidité pour se transformer en simple succession d'images.
    Citation Envoyé par SeniorEric Voir le message
    1 l'affichage est tjrs sacadé si je laisse la souris immobile alors que là le code est plutot simple
    2 j'ai une question sur la vie des threads ; dans le programme il y a un bouton pour démarrer le chrono, un pour suspendre, reprendre et stopper.
    Une fois qu'il est stoppé, donc aprés la méthode stop ( qui est deprecated d'ailleurs ) comment on peut le tester pour savoir si on peut en créer un autre en appuyant sur démarrer ?
    NE JAMAIS UTILISER LA METHODE STOP DE THREAD. D'une manière générale, ne jamais appeler une méthode dépréciée. Un thread s'arrête soit de lui-même, lorsqu'il a finit son traitement, soit s'il s'agit d'une boucle infinie, on utilisera un booléen volatile pour contrôler la boucle. Idem pour suspend/resume.
    Citation Envoyé par SeniorEric Voir le message
    Ou bien, une fois qu'on a fait stop, comment redémarrer sans relancer le programme ?
    On recrée une nouvelle instance de thread. Un thread ne peut être exécuté 2 fois.

    Citation Envoyé par SeniorEric Voir le message
    et aussi est ce identique d'implémentar runnable et d'étendre Thread ?
    Oui et non. La plupart du temps (99,99% des cas) implémenter Runnable est préférable : on peut facilement mettre en place un pool de thread pour exécuter la tâche plusieurs fois. Si la tâche n'a pas d'état (ce qui est toujours préférable (il y a le problème du booléen de contrôle qui est un état, qu'on peut régler soit par callback, soit évuentuellement par threadlocal (la solution du callback me semble mieux, surtout qu'en l'améliorant on peut en faire un moniteur de progression)), on pourra même utiliser la même instance (donc une seule et unique instance).
    Pour les cas, où on a besoin d'avoir la référence du thread qui exécute le runnable, tel que ça ne soit pas le thread courant lors de l'invocation, il y a d'autres moyens de s'en sortir que d'étendre Thread, mais c'est surtout par économie/fainéantise qu'on va le faire.

    Par rapport à ton code, je n'ai pas tout regardé, mais j'ai vu rapidement :

    • deroulement.sleep(33);Ce n'est pas une bonne idée déjà que le runnable connaisse l'instance de thread qui l'exécute : ça sclérose l'architecture de l'application (le runnable ne peut pas être exécuté sans connaître l'instance de thread, donc toute utilisation avec d'autres classes plus simples ou mieux adaptées sera imposssible).
      Surtout la méthode sleep() est statique : ce n'est pas une méthode d'instance mais de classe. Tu as l'impression de suspendre ici le bon thread, alors que c'est juste une chance. La méthode sleep() suspend le thread courant qui se trouve être par chance (par l'implémentation) le thread qui fait tourner le runnable. Un oubli, une confusion, et hop, plus rien ne fonctionne correctement. Par exemple, ta méthode démarrer n'étant pas synchronisée (une erreur je suppose), tu pourrais tout d'un coup, avec la volonté de gérer un système qui démarre automatiquement des chronomètres, mettre en place un système qui fait que 2 threads appellent la méthode démarrer concurrement, donc 2 threads lancés avec le même runnable, donc un n'est plus lié au runnable.
      D'une manière générale, on n'appelle jamais une méthode static sur une instance, toujours par la classe : Thread.sleep(33);
    • Comme je te l'ai déjà dit, tu n'as aucune assurance que ton programme se déroule normalement sans arrêt au rythme voulu : il peut se passer plein de chose sur une machine en parallèle de ton programme et rendre absurde ton décompte de temps. Calcule donc le temps écoulé comme un temps écoulé, et non pas comme une somme incrémentale :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      public void run() {
      		long time=System.currentTimeMillis();
      		while (tempsEcoule<duree) {
      		try {
      			Threed.sleep(33);
      		} catch (InterruptedException e) {
      			tempEcoule=duree;
      		} 
      		tempsEcoule+=System.currentTimeMillis()-time ;
      		time=System.currentTimeMillis();
      		proprietaire.repaint() ;
      		}
       
      	}
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  15. #55
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2016
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2016
    Messages : 85
    Points : 20
    Points
    20
    Par défaut
    j'ai fini par regarder le corrigé et c'est à base de wait et notify. Pas de suspend / resume ni stop, par contre j'ai pas encore tout compris. Voici le code de la classe Chorno

    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
    110
    111
    112
    113
    114
    115
    116
    117
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Rectangle;
     
    import javax.swing.JComponent;
     
    public class Chrono implements Runnable
    {
    	private int x, y, diametre;
    	private JComponent proprietaire;
    	private Thread deroulement;
    	private long tempsEcoule = 0; // exprime en millisecondes
    	private long duree; // nombre de millisecondes pour un tour complet
    	private long momentDebut = 0;
    	private long momentSuspension;
    	private boolean continuer;
    	private boolean finir;
     
    	/* - proprietaire donne le composant devant contenir l'image du chronometre.
    	 * - duree donne le temps en secondes mis pour que le chronometre fasse un tour complet,
    	 * apres ce temps, le chronometre s'arrete.
    	 * - x et y indiquent  les coordonnees du coin superieur gauche du carre 
    	 * circonscrit au chronometre
    	 *- diametre indique le diametre du chronometre*/
    	public Chrono(JComponent proprietaire, int duree, 	int x, int y, int diametre) {
    		this.duree = duree * 1000;
    		this.x = x;
    		this.y = y;
    		this.diametre = diametre;
    		this.proprietaire = proprietaire;
    	}
     
    	/* Demarre le chronometre */
    	public void demarrer()  {   
    		if (enFonctionnement()) 
    		{
    			arreter();
    			try
    			{
    				deroulement.join();
    			}
    			catch(InterruptedException exc) {
    				exc.printStackTrace();
    			}
    		}
    		deroulement = new Thread(this);
    		deroulement.start();
    	}
     
    	/* Suspend le deroulement du temps ; ce deroulement pourra etre repris 
    	 * dans l'etat ou il se trouvait par la methode reprendre */
    	public void suspendre() {     
    		if (enFonctionnement()  && continuer) {
    			momentSuspension = System.currentTimeMillis();
    			continuer = false;
    		}
    	}
     
    	/* Si le chronometre est en fonctionnment mais a ete suspendu, 
    	 * il recommence a tourne r*/ 
    	public synchronized  void reprendre() { 
    		if (enFonctionnement() && !continuer) {  
    			momentDebut +=  System.currentTimeMillis() - momentSuspension;
    			continuer = true;
    			notifyAll();
     
    		}
    	}
     
    	/* Arrete le chronometre. Une fois arrete, le chronometre ne peut
        repartir qu'avec la methode demarrer, au debut du décompte du temps*/
    	public synchronized void arreter() {
    		if (enFonctionnement()) {
    			finir = true;
    			notifyAll();
    		}
    	}
     
    	/* Fait tourner le chronometre */
    	public void run() {
    		Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
    		continuer = true;
    		finir = false;
    		momentDebut = System.currentTimeMillis();
    		while((tempsEcoule < duree) && (!finir))
    		{
    			tempsEcoule = System.currentTimeMillis() - 
    			momentDebut;
    			proprietaire.repaint(new Rectangle(x, y, diametre, diametre));
    			try {
    				Thread.sleep(200);
    				synchronized(this) {
    					while (!continuer && !finir) wait();
    				}
    			}
    			catch(InterruptedException e){
    				e.printStackTrace();
    			}
    		}
    	}
     
    	/* Retourne true si le chronometre est en fonctionnement,  eventuellement suspendu 
    	 * et false si le chronometre n'est pas demarre, ou bien a ete arrete, ou bien a fini de tourner*/
    	public boolean enFonctionnement() {
    		return (deroulement!=null) && (deroulement.isAlive());
    	}
     
    	/* Dessine le chronometre selon le temps pendant lequel il a tourne  depuis qu'il a ete mis en fonctionnement */
    	public void dessine(Graphics g) {
    		g.setColor(Color.YELLOW);
    		g.fillArc(x, y, diametre, diametre, 90,
    				(int)(360 - tempsEcoule * 360 / duree));
    		g.setColor(Color.GREEN);
    		g.fillArc(x, y, diametre, diametre,90,
    				(int)(-tempsEcoule * 360 / duree));
    	}
    }
    je comprends pas bien le join dans demarrer(), et pourquoi on fait pas de wait dans suspendre(), et pourquoi le wait se fait dans le run() ???
    Et surtout cette partie

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    try {
    				Thread.sleep(200);
    				synchronized(this) {
    					while (!continuer && !finir) wait();
    				}
    			}
    Sinon de manière plus générale, doit on tout le temps gérer les accès concurrents à une ressource en java ? Par exemple, quand je faisais du SGBDR, les locks étaient déjà gérés, on avait rien à faire de spécial. Sauf quand ça merdait...
    Pour l'exo sur les disques qui montent, il faudrait que j'implémente l'acès à la liste de disque avec des wait et notify ?

  16. #56
    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
    Citation Envoyé par SeniorEric Voir le message
    j'ai fini par regarder le corrigé et c'est à base de wait et notify. Pas de suspend / resume ni stop, par contre j'ai pas encore tout compris.
    Les méthodes wait() et notify()/notifyAll() s'appliquent à l'instance d'objet pour le thread en cours. Ainsi machin.wait(); suspend le thread qui exécute wait() et machin.notify(); envoie un signal qui débloque un thread en attente sur l'instance de machin (un qui a fait machin.wait(); (machin.notifyAll(); débloque tous les threads en attente sur machin. Il est nécessaire que le thread (qui appelle wait() ou notify()) ait un verrou sur l'instance pour le thread. En revanche, je ne vois pas trop l'intérêt d'utiliser wait() et notify() pour faire un chrono. Ça me semble plutôt un cas saugrenu d'application. Une file d'attente est un cas plus classique et évident d'application : quand le file est vide, on fait un wait pour éviter que le thread qui consome les éléments de la file tourne à vide continuellement (donc consomme du cpu en risque de mettre en famine les autres threads) pour regarder s'il y a des éléments à traiter et le thread qui met des éléments dans la file appelle notify() pour le débloquer.

    Citation Envoyé par SeniorEric Voir le message
    je comprends pas bien le join dans demarrer(), et pourquoi on fait pas de wait dans suspendre(), et pourquoi le wait se fait dans le run() ???
    La méthode join() permet d'attendre que le thread pour laquelle elle est invoquée soit terminé. Juste avant on appelle arreter() qui fait un notifyAll pour débloquer le thread en attente (un autre thread donc que celui qui appelle notifyAll(), et qui va donc s'arrêter en conséquence. Il faut donc attendre qu'il soit complètement arrêter pour en démarrer un nouveau. On a besoin de faire ça uniquement parce que demarrer() fait en fait un redémarrage lorsque le chrono est déjà démarré. Si on faisait simplement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    if (enFonctionnement()) {
        return; // si chrono déjà démarré, on ne fait rien
    }
    On n'aurait pas besoin du join().

    Citation Envoyé par SeniorEric Voir le message

    Et surtout cette partie

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    try {
    				Thread.sleep(200);
    				synchronized(this) {
    					while (!continuer && !finir) wait();
    				}
    			}
    C'est la structure classique de mise en place d'un verrou wait/notify pour gérer l'accès concurrent. Le Thread.sleep() fait une pause de 200ms.
    Le synchronized(this) met un verrou d'exclusion mutuelle sur l'instance this pour le thread en cours parce que c'est nécessaire pour appeler wait().
    Lorsque this reçoit un signal (un notify ou notifyAll) le thread en attente est débloqué, reteste la condition de vie, si elle est vraie repasse en attente (d'un signal), sinon, on continue, et donc on termine le thread.

    Citation Envoyé par SeniorEric Voir le message
    Sinon de manière plus générale, doit on tout le temps gérer les accès concurrents à une ressource en java ? Par exemple, quand je faisais du SGBDR, les locks étaient déjà gérés, on avait rien à faire de spécial. Sauf quand ça merdait...
    Attention, ce n'est pas exactement le même type de verrou (et les verrous ne sont pas tous gérés implicitement en SQL : sur un SELECT par exemple, pas de verrou sans faire un lock/holdlock/updlock etc). Les verrous de bases de données empêchent que dès qu'une modification est faite et non commitée, on empêche les autres de s'en servir (le lire, ou écrire) : il s'agit plutôt d'un verrou d'intégrité. On peut verrouiller des lignes ou des tables entières, parce que ces structures sont des structures inhérentes à la notion de SGBDR.
    En Java, il n'y a pas de modification autre que dans le cas d'une modification de variable primitive ou de référence d'objet. Toutes les autres modifications ne sont forcément que des modifications de plusieurs variables primitives ou références d'objet : et comme on ne peut garantir l'exécution atomique de plusieurs instructons successives, les exécuter concurrement dans plusieurs threads risquent de tout faire foirer (d'avoir des données non complètes/intègres lues par un thread).
    La nécessité de verrous en Java est indispensable en multi-thread pour des séquences d'instructions qui manipulent des données de manière non atomique (et également par rapport à une problématique de cache en multiprocesseur).
    Par exemple, voici 2 sequences :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    if ( object!=null && dernier<tableau.length ) {
       tableau[dernier]=objet;
       dernier+=1; // j'aurais pu faire dernier++ mais c'est pour que tu vois mieux que c'est deux instructions différentes
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    if ( dernier>0 ) {
       dernier-=1;
       object=tableau[dernier];
    }
    on gère ici une pile, tel que dernier est le prochain emplacement disponible pour y placer un objet

    Maintenant, prenons
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    String[] tableau=new String[3];
    et que dernier vaut 0 (il n'y a donc rien dans le tableau.

    Imagine qu'un thread (1) appelle la première séquence et un autre (1) aussi. L'exécution de chaque instruction est complètement imprévisible : peut-être que c'est le premier qui va tout faire puis le second va commencer, ou l'un va exécuter une seule instruction et l'autre 2 puis le premier 3, puis le second une seule, etc...
    Mettons qu'il se passe ça
    1. (1) teste 0<3 : vrai, il continue
    2. (2) test 0<3 : vrai, il continue
    3. (1) met "truc" dans tableau[0],
    4. (2) met "machin" dans tableau0] : patatras : il écrase l'objet ("truc") de l'autre
    5. (1) fait dernier+1 => dernier vaut 1
    6. (2) fait dernier+1=> dernier vaut 2

    on a dernier = 2
    Au lieu d'avoir
    truc machin null
    on a
    machin null null
    Tu as perdu un objet, ta pile est foireuse, et tu auras en plus une NullPointerException, alors qu'on empêche d'écrire des null dans le tableau dans la méthode d'écriture.
    Voire pire, si dernier est 2 au moment de l'appel, on aura une ArrayIndexOutOfBoundException.

    On ne peut pas gérer ça de manière implicite comme pour les SGBDR : déjà il est impossible de déterminer toutes les séquences possibles de code, donc il faudrait le faire systématiquement pour toutes les méthodes, y compris celle pour lesquelles ça ne sert strictement à rien. Donc une énorme perte de temps dans l'exécution des programmes.
    Pourquoi ce n'est pas systématiquement pour une HashMap par exemple : parce que là aussi, dans beaucoup cas, c'est inutile et donc ce serait ralentir inutilement les programmes.
    Dans une base de données, la problématique de modifier partiellement un enregistrement en plusieurs étapes est un cas bien identifié et donc géré de manière implicite.
    En revanche, un select suivi d'un update de l'enregistrement lu qui doit être atomique (tous les autres process doivent attendre que les deux soient fait avant de faire ce qu'ils ont à faire) ne l'est pas : parce que si on le faisait systématiquement, on plomberait inutilement les temps de réponse.

    Pour ce qui le cas de la problématique de cache : pour des raisons de performances, chaque processeur dispose d'une "copie" d'une variable. Ainsi si un thread est exécuté par un processeur pour modifier la valeur de la variable (valeur de variable primitive ou référence d'objet), un autre thread exécuté par un autre processeur n'aura pas forcément déjà cette valeur.
    Pour gérer ça on peut utiliser les verrous (par synchronized) ou simplement déclarer la variable volatile.



    Citation Envoyé par SeniorEric Voir le message
    Pour l'exo sur les disques qui montent, il faudrait que j'implémente l'acès à la liste de disque avec des wait et notify ?
    Cela est nécessaire oui, justement par ce que la modification et la lecture dans une liste ne sont pas des ordres atomiques.
    En revanche, il y a maintes façons de gérer l'accès concurrent selon les besoins :
    • synchronized
    • java.util.concurrent.locks.Lock
    • wait/notify
    • volatile
    • classes implémentées (comme StringBuffer(vs StringBuilder), ConcurrentHashMap (vs HashMap), ou Stack(vs Deque)) ou fabrique comme les méthodes du type Collections.synchronized**

    Pour l'accès concurrent à une liste, le plus simple est de faire du synchronized. Ensuite, tu peux chercher à optimiser avec java.util.concurrent.locks.Lock. Ou utiliser Collections.synchronizedList(List) ou utiliser une CopyOnWriteArrayList. Essayer les différentes solutions et les comparer (difficulté d'implémentation, performances d'éxécution) peut être intéressant comme exercice.
    Le wait/notify on l'utilise pour éviter qu'un thread tourne inutilement à vide.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  17. #57
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2016
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2016
    Messages : 85
    Points : 20
    Points
    20
    Par défaut
    Merci encore pour ces réponses détaillées. Je n'ai pas encore tout compilé, mais j'y compte. J'ai essayé du synchronized sur les ballons : est ce que c'est bon, j'avoue que je comprends pas tout bien encore.
    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
    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
    168
    package disquesaleatoires;
     
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.FlowLayout;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.util.ArrayList;
    import java.util.Random;
    import java.util.Timer;
    import java.util.TimerTask;
    import java.util.concurrent.ThreadLocalRandom;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
     
     
     
     
     
    class Fenetre extends JPanel  {
    	private Color couleurdefond ;
    	private ArrayList<Disque> mesdisques ;
    	private int tempo_disque = 0 ; // pour empecher d'avoir des nouveaux ballons trop vite et permettre le montée rapide des ballons
    	Fenetre(Color couleur,final ArrayList<Disque> mesdisques) {
    		this.couleurdefond = couleur ;
    		this.mesdisques = mesdisques ;
     
    		setLayout(new FlowLayout());
    		setBackground(couleur) ;
     
    		addMouseListener(new MouseAdapter() {
     
    			@Override
    			public void mouseClicked(MouseEvent e) {
     
    			}
    			public void mousePressed(MouseEvent e) {
    			  synchronized(this) {
    				for (Disque disque : mesdisques) {
     
    					int x = disque.getX(); int y = disque.getY();
     
    					if (disque.estdedans(e.getX(),e.getY())) {
     
    						mesdisques.remove(disque);
    						//System.out.println("Est dedans"+ disk_destroyed.getX()); 
    						break ;
    		        	}
    	        	 } 
    			  }
    			}
     
    		});
    	}
    	public void paint(Graphics g) {
     
    		 super.paint(g);
    		 for (Disque mondisque : mesdisques) {
    			 mondisque.Afficher(g) ;
    		 }
     
    	}
    	public void anim() {
    		 final int width=600;//getWidth();
    		 final int height=400;//getHeight();
    		 //System.out.println("Ajout disque "+width+" "+ height) ;
     
    		 if ( (tempo_disque == 0) || (tempo_disque == 25) ) {
    			 if ( tempo_disque == 25 ) tempo_disque = 0 ;
    			 int diametre = ThreadLocalRandom.current().nextInt(100) ;
    			 int abscisse = ThreadLocalRandom.current().nextInt(width-diametre) ;
    			 int ordonnee = height -50 ;
    			 int rcolor = ThreadLocalRandom.current().nextInt(255) ;
    			 int gcolor = ThreadLocalRandom.current().nextInt(255) ;
    			 int bcolor = ThreadLocalRandom.current().nextInt(255) ;
    			 Disque disque = new Disque(abscisse,ordonnee,diametre,rcolor,gcolor,bcolor) ;
    			 synchronized(this){ mesdisques.add(disque); }
     
    		 }
     
    		 tempo_disque+=1 ;
    		 synchronized(this){
    		   for (Disque mondisque : mesdisques) {
     
    			 mondisque.setY(mondisque.getY() -1 );
     
    		   }
    		 }
    		 repaint();
    	}
    }
     
    class Disque {
    	private int XO,YO,diam,rC,gC,bC ;
    	Disque(int XO,int YO,int diam,int rC,int gC,int bC) {
    		this.XO = XO ;this.YO = YO ;this.diam = diam ;this.rC = rC ;this.gC = gC ;this.bC = bC ;
    		//g.setColor(new Color(rC,gC,bC)) ;
    		//g.fillOval(XO, YO, diam, diam) ;
    		//g.dispose() ; 
    	}
    	void Afficher(Graphics g) {
    		g.setColor(new Color(this.rC,this.gC,this.bC)) ;
    		g.fillOval(this.XO, this.YO, this.diam, this.diam) ;
    		//g.dispose() ; 
    	}
    	int getDiametre() {
    		return this.diam ;
    	}
    	void setDiametre(int diametre) {
    		this.diam = diametre ;	
    	}
    	int getX() {
    		return this.XO ;
    	}
    	int getY() {
    		return this.YO ;
    	}
    	void setX(int x) {
    		this.XO = x ;
    	}
    	void setY(int y) {
    	    this.YO = y ;
    	}
    	void setPosition(int x,int y) {
    		this.XO = x ; this.YO = y ;
    	}
    	public boolean estdedans (int x,int y) {
    		//System.out.println("est dedans "+x+" "+this.x+" "+y+" "+this.y) ;
    		if (((x>=this.XO) && (x<= this.XO+diam)) && ((y>=this.YO)&&(y<=this.YO+diam))) {
    			//System.out.println("est dedans ") ;
    			return true ;
    		}
    		else return false ;
    	}
    }
    public class DisquesAleatoires {
     
    	public static void main(String[] args) {
    		ArrayList<Disque> mesdisques = new ArrayList<Disque>() ;
    		long temps = 50;                      // délai avant de répéter la tache : 2000 = 2  seconde
    	    long startTime = 0;                    // délai avant la mise en route (0 demarre immediatement)
    	    Timer timer = new Timer();             // création du timer
    		Color couleur = Color.WHITE ;
    		JFrame frame = new JFrame("Disques Aléatoires");
    		frame.setSize(600,400);
    		final Fenetre panel = new Fenetre(couleur,mesdisques) ;
     
    		frame.add(panel) ;
     
    		TimerTask tache = new TimerTask() {     // création et spécification de la tache à effectuer
    	         @Override
    	         public void run() {
    	        	panel.anim() ;
     
    	         }
    	     };
    	    timer.scheduleAtFixedRate(tache,startTime,temps);  // ici on lance la mecanique
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		frame.setLocation(200, 200);
     
    		frame.setResizable(true) ;
    		frame.setVisible(true);
     
    	}
    }
    j'ai commencé un autre exo et je bloque sur un truc simple je pense mais j'ai besoin de tes lunières .

    On a une classe Bulle :
    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
    package applibulles;
     
    import java.awt.Color;
    import java.awt.Graphics;
    import java.util.Random;
     
    import javax.swing.JPanel;
     
    public class Bulle extends Thread {
    	//la fenetre dans laquelle le disque se deplace
    	private ClicBulles panneauBulles;
     
    	//abscisse et ordonnee du centre du disque
    	private int abs, ord;
     
    	//largeur et hauteur de la fenetre dans laquelle la ebulle se d�place
    	private int largeur, hauteur;
     
    	//le rayon du disque
    	private int rayon;
     
    	//la couleur du disque
    	private Color couleur;
     
    	//param�tre qui regle la distance parcourue par le disque � chaque deplacement
    	private int pas;
     
    	//(alpha, beta) donne la direction du deplacement
    	private float alpha, beta;
     
    	//le temps (minimum) entre deux deplacements
    	private int pause = 10;
     
    	Random alea = new Random();
     
    	public Bulle(int x, int y, int l, int h, ClicBulles panneauBulles) {
    		abs = x;
    		ord = y;
    		largeur = l;
    		hauteur = h;
    		this.panneauBulles = panneauBulles;
    		rayon = (Math.abs(alea.nextInt())) % 15 + 3;
    		pas = (Math.abs(alea.nextInt())) % 5 + 1;
    		alpha = 2 * alea.nextFloat() - 1;
    		beta = 2 * alea.nextFloat() - 1;
    		couleur = new Color((Math.abs(alea.nextInt())));
    	}
     
    	//indique si le disque est totalement sorti de la fenetre
    	public boolean sortie() {
    		if ((abs + rayon < 0) || (abs + rayon > largeur) 
    				||(ord + rayon < 0) || (ord - rayon > hauteur))
    			return true;
    		else return false;
    	}
     
    	//dessine le disque dans la couleur indiqu�e
    	public void dessiner(Graphics g) {
    		g.setColor(couleur);
    		g.fillOval(abs - rayon, ord - rayon, 
    				2 * rayon, 2 * rayon);
    	}
     
    	/* deplace le disque depuis son point de d�part en 
    	 * suivant la direction (alpha, beta) jusqu'� ce 
    	 * qu'il sorte de la fenetre */
    	public void run() {
    		float absF = abs, ordF = ord;
     
    		while (!sortie()){
    			//A COMPLETER
    		}
    		panneauBulles.getLesBulles().remove(this);
    	}
    }
    et je veux l'instancier :
    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
    public class ClicBulles extends JPanel {
    	private static final long serialVersionUID = 1L;
    	private ArrayList<Bulle>  lesBulles = new ArrayList<Bulle>();
    	public ClicBulles()
    	{
    		setBackground(Color.WHITE);
    		//setPreferredSize(new Dimension(300, 300));
    		addMouseListener(new MouseAdapter()
    		{
    			public void mouseClicked(MouseEvent evt) {
    				Bulle mabulle = new Bulle(evt.getX(),evt.getY(),getWidth(),getHeight(),this) ;
    				/* A COMPLETER pour creer une bulle, l'ajouter aux bulles et  faire
    				 * demarrer cette bulle dans un nouveau thread */
    			}  
    		});
     
    	}
    et le compilo dit que this représente MouseAdapter, alors qu'il devrait représenter ClicBulle, non ? L'objet en cours ?

  18. #58
    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
    Citation Envoyé par SeniorEric Voir le message
    Merci encore pour ces réponses détaillées. Je n'ai pas encore tout compilé, mais j'y compte. J'ai essayé du synchronized sur les ballons : est ce que c'est bon, j'avoue que je comprends pas tout bien encore.
    Tu as oublié de synchroniser le parcourt de la liste dans la méthode paint(). Tu aurais pu simple synchroniser sur l'instance de liste plutôt que sur this. L'intérêt de restreindre le verrou uniquement sur l'objet concerné par l'accès concurrent et, donc, éventuellement de permettre de synchroniser de manière indépendante sur d'autres objets au besoin.

    Citation Envoyé par SeniorEric Voir le message
    j'ai commencé un autre exo et je bloque sur un truc simple je pense mais j'ai besoin de tes lunières .
    [...]

    et le compilo dit que this représente MouseAdapter, alors qu'il devrait représenter ClicBulle, non ? L'objet en cours ?
    Le this ici fait bien référence à l'objet en cours, mais sa classe n'est pas ClicBulle, mais une classe anonyme qui étend MouseAdapter.
    Quand tu fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    machin = new NomDeClasseOuDinterface {
     
          /* etc */
     
    }
    Tu déclares une nouvelle classe, dite anonyme (sans nom donc). C'est comme si tu avais déclaré une classe locale :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class Toto extends NomDeClasseOuDinterface {
     
          /* etc */
     
    }
    machin = new Toto();
    C'est juste une facilité syntaxique qui évite d'avoir justement a créer une classe qu'on va utiliser qu'une seule fois.

    A noter que si tu regardes dans ton dossier de compilation, tu verras bien un .class correspondant à cette classe anonyme.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  19. #59
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2016
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2016
    Messages : 85
    Points : 20
    Points
    20
    Par défaut
    comme ça ?

    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
    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
    168
    169
    170
    package disquesaleatoires;
     
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.FlowLayout;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.util.ArrayList;
    import java.util.Random;
    import java.util.Timer;
    import java.util.TimerTask;
    import java.util.concurrent.ThreadLocalRandom;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
     
     
     
     
     
    class Fenetre extends JPanel  {
    	private Color couleurdefond ;
    	private ArrayList<Disque> mesdisques ;
    	private int tempo_disque = 0 ; // pour empecher d'avoir des nouveaux ballons trop vite et permettre le montée rapide des ballons
    	Fenetre(Color couleur,final ArrayList<Disque> mesdisques) {
    		this.couleurdefond = couleur ;
    		this.mesdisques = mesdisques ;
     
    		setLayout(new FlowLayout());
    		setBackground(couleur) ;
     
    		addMouseListener(new MouseAdapter() {
     
    			@Override
    			public void mouseClicked(MouseEvent e) {
     
    			}
    			public void mousePressed(MouseEvent e) {
    			  synchronized(mesdisques) {
    				for (Disque disque : mesdisques) {
     
    					int x = disque.getX(); int y = disque.getY();
     
    					if (disque.estdedans(e.getX(),e.getY())) {
     
    						mesdisques.remove(disque);
    						//System.out.println("Est dedans"+ disk_destroyed.getX()); 
    						break ;
    		        	}
    	        	 } 
    			  }
    			}
     
    		});
    	}
    	public void paint(Graphics g) {
     
    		 super.paint(g);
    		 synchronized(mesdisques) {
    		    for (Disque mondisque : mesdisques) {
    			 mondisque.Afficher(g) ;
    		    }
    		 }
     
    	}
    	public void anim() {
    		 final int width=600;//getWidth();
    		 final int height=400;//getHeight();
    		 //System.out.println("Ajout disque "+width+" "+ height) ;
     
    		 if ( (tempo_disque == 0) || (tempo_disque == 25) ) {
    			 if ( tempo_disque == 25 ) tempo_disque = 0 ;
    			 int diametre = ThreadLocalRandom.current().nextInt(100) ;
    			 int abscisse = ThreadLocalRandom.current().nextInt(width-diametre) ;
    			 int ordonnee = height -50 ;
    			 int rcolor = ThreadLocalRandom.current().nextInt(255) ;
    			 int gcolor = ThreadLocalRandom.current().nextInt(255) ;
    			 int bcolor = ThreadLocalRandom.current().nextInt(255) ;
    			 Disque disque = new Disque(abscisse,ordonnee,diametre,rcolor,gcolor,bcolor) ;
    			 synchronized(mesdisques){ mesdisques.add(disque); }
     
    		 }
     
    		 tempo_disque+=1 ;
    		 synchronized(mesdisques){
    		   for (Disque mondisque : mesdisques) {
     
    			 mondisque.setY(mondisque.getY() -1 );
     
    		   }
    		 }
    		 repaint();
    	}
    }
     
    class Disque {
    	private int XO,YO,diam,rC,gC,bC ;
    	Disque(int XO,int YO,int diam,int rC,int gC,int bC) {
    		this.XO = XO ;this.YO = YO ;this.diam = diam ;this.rC = rC ;this.gC = gC ;this.bC = bC ;
    		//g.setColor(new Color(rC,gC,bC)) ;
    		//g.fillOval(XO, YO, diam, diam) ;
    		//g.dispose() ; 
    	}
    	void Afficher(Graphics g) {
    		g.setColor(new Color(this.rC,this.gC,this.bC)) ;
    		g.fillOval(this.XO, this.YO, this.diam, this.diam) ;
    		//g.dispose() ; 
    	}
    	int getDiametre() {
    		return this.diam ;
    	}
    	void setDiametre(int diametre) {
    		this.diam = diametre ;	
    	}
    	int getX() {
    		return this.XO ;
    	}
    	int getY() {
    		return this.YO ;
    	}
    	void setX(int x) {
    		this.XO = x ;
    	}
    	void setY(int y) {
    	    this.YO = y ;
    	}
    	void setPosition(int x,int y) {
    		this.XO = x ; this.YO = y ;
    	}
    	public boolean estdedans (int x,int y) {
    		//System.out.println("est dedans "+x+" "+this.x+" "+y+" "+this.y) ;
    		if (((x>=this.XO) && (x<= this.XO+diam)) && ((y>=this.YO)&&(y<=this.YO+diam))) {
    			//System.out.println("est dedans ") ;
    			return true ;
    		}
    		else return false ;
    	}
    }
    public class DisquesAleatoires {
     
    	public static void main(String[] args) {
    		ArrayList<Disque> mesdisques = new ArrayList<Disque>() ;
    		long temps = 50;                      // délai avant de répéter la tache : 2000 = 2  seconde
    	    long startTime = 0;                    // délai avant la mise en route (0 demarre immediatement)
    	    Timer timer = new Timer();             // création du timer
    		Color couleur = Color.WHITE ;
    		JFrame frame = new JFrame("Disques Aléatoires");
    		frame.setSize(600,400);
    		final Fenetre panel = new Fenetre(couleur,mesdisques) ;
     
    		frame.add(panel) ;
     
    		TimerTask tache = new TimerTask() {     // création et spécification de la tache à effectuer
    	         @Override
    	         public void run() {
    	        	panel.anim() ;
     
    	         }
    	     };
    	    timer.scheduleAtFixedRate(tache,startTime,temps);  // ici on lance la mecanique
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		frame.setLocation(200, 200);
     
    		frame.setResizable(true) ;
    		frame.setVisible(true);
     
    	}
    }
    Pour le reste, il faut donc que je passe par une variable de la classe clicbulles qui serait initialisée à this ?

  20. #60
    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
    Oui, comme ça (Maintenant, globalement cette manière de faire, ça pose un problème : si le thread non graphique qui bloque la liste de disques prend du temps, le thread graphique va être bloqué pendant ce temps, et donc tu vas avoir du freeze : la solution serait de passer par de la copie, de manière à ce que les deux threads ne travaille jamais sur les mêmes instances de liste/tableau).

    Pour le this dans le MouseAdapter, tu peux toujours référencer l'instance de classe englobante par le nom de la classe, suivi de .this, donc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    addMouseListener(new MouseAdapter()
    		{
    			public void mouseClicked(MouseEvent evt) {
    				Bulle mabulle = new Bulle(evt.getX(),evt.getY(),getWidth(),getHeight(),ClicBulles.this) ;
    				/* A COMPLETER pour creer une bulle, l'ajouter aux bulles et  faire
    				 * demarrer cette bulle dans un nouveau thread */
    			}  
    		});
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

Discussions similaires

  1. [Python 3.X] Question de débutant : Problème de classes dans un autre fichier
    Par amelyfred dans le forum Général Python
    Réponses: 4
    Dernier message: 17/06/2015, 12h00
  2. Réponses: 3
    Dernier message: 10/04/2014, 17h12
  3. freeze de la GUI et autres questions débutantes
    Par chaima01 dans le forum Débuter
    Réponses: 1
    Dernier message: 30/04/2013, 19h54
  4. [Débutant] Autre question sur Const
    Par Faiche dans le forum Débuter
    Réponses: 9
    Dernier message: 21/10/2008, 14h08
  5. [HyperFile] 2 questions de débutant
    Par khan dans le forum HyperFileSQL
    Réponses: 2
    Dernier message: 29/04/2002, 23h18

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