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

EDT/SwingWorker Java Discussion :

Actions concurrentes dans EDT


Sujet :

EDT/SwingWorker Java

  1. #1
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut Actions concurrentes dans EDT
    Bonjour,
    Cette discussion est une suite sur celle de Swing et Thread que j'ai initié le 13 février (http://www.developpez.net/forums/d13...-swing-thread/
    Un nouveau problème apparait.
    J'utilise donc SwingWorker pour ne pas bloquer l'EDT mais celui-ci empile dans l'EDT 100 requêtes d'affichage d'images. En même temps l'appui sur un bouton modifie un JLabel ce qui va aussi s'inscrire dans l'EventQueue par l'intermédiaire de l'InvokeLater. Malheureusement (du fait d'une temporisation pour les images) la mise à jour du label ne se fait pas. Une idée ?
    Mon code qui ne met pas à jour le JLabel
    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
    package jeux.memory.images;
     
    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.Font;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
     
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JProgressBar;
    import javax.swing.SwingUtilities;
     
    public class Diaporama extends JFrame implements ActionListener
    {
    	private GestionDonnees gestionDonnees;
    	private int delai;
    	private JLabel afficheDelai;
    	private Cartouche cartouche;
    	private static JPanel panneauCentral = new JPanel();
    	private JButton plus, moins;
    	private JProgressBar progression;
    	private JLabel test;
     
     
    	public Diaporama(GestionDonnees gd)
    	{
    		super("Diaporama");
            this.gestionDonnees = gd;
            this.setSize (800,600);
            this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    //        this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
            this.setLocationRelativeTo(null);
     
            JPanel panneauCentral = new JPanel();
            JPanel panneauBas = new JPanel();
     
            progression = new JProgressBar(0,100);
            progression.setPreferredSize(new Dimension(500,20));
            progression.setStringPainted(true);
            plus = new JButton("+");
            plus.addActionListener (this);
     
            moins = new JButton("-");
            moins.addActionListener (this);
     
    		delai = 3000;
    		afficheDelai = new JLabel("timing entre deux images = " + (int)(delai/1000)  + " s");
     
    		panneauBas.add(progression);
    		panneauBas.add(plus);
    		panneauBas.add(moins);
    		panneauBas.add(afficheDelai);
     
    		String liste = gestionDonnees.getImages(0);
    		String nom = liste.split(";")[0];
    		ListeImages listeImages = new ListeImages(nom,liste,800);
    		cartouche = new Cartouche(listeImages);
    		panneauCentral.add(cartouche);
     
    		getContentPane().add(panneauBas, BorderLayout.SOUTH);
    		getContentPane().add(panneauCentral,BorderLayout.CENTER);
     
    		setVisible(true);
    		afficher();
    	}
     
    	private void afficher()
    	{
    		new Thread(new Runnable()
    		{
    			public void run()
    			{
    				for (int i = 1 ; i < gestionDonnees.getNbDonnees() ; i++)
    				{
    					try
    					{
    						Thread.sleep(delai);
    					}
    					catch (InterruptedException e)
    					{
    						// TODO Auto-generated catch block
    						e.printStackTrace();
    					}
    					String listeImages = gestionDonnees.getImages(i);
    					String nom = gestionDonnees.getNom(i);
    					final ListeImages images = new ListeImages(nom,listeImages,800);
    					SwingUtilities.invokeLater(new Runnable()
    					{
    						public void run()
    						{
    							cartouche.modifieImages(images);
    							cartouche.revalidate();
    						}
    					});
    				}
    			}
     
    		}).start();
    	}
     
    	public static void main(String[] args)
    	{
            javax.swing.SwingUtilities.invokeLater(new Runnable() 
            {
                private Diaporama fenetre;
     
    			public void run() 
                {
                	fenetre = new Diaporama(new GestionDonnees());
                }
            });
    	}
     
    	public void actionPerformed(ActionEvent evt)
    	{
    		if (evt.getSource() == plus) augmenterDelai();
    		if (evt.getSource() == moins) diminuerDelai();
    	}
     
    	private void diminuerDelai()
    	{
    		System.out.println("diminuer délai");
    		delai = Math.max(1000, delai -1000);
    		Runnable code = new Runnable() 
    		{
    		    public void run() 
    		    {
    		    	afficheDelai.setText("timing entre deux images = " + delai  + " s");
    		    }
    		};
    		if (SwingUtilities.isEventDispatchThread()) 
    		{
    		    code.run();
    		} 
    		else 
    		{
    			SwingUtilities.invokeLater(code);
    		}		
    //		afficheDelai.revalidate();
    	}
     
    	private void augmenterDelai()
    	{
    		System.out.println("augmenter délai");
    	}
    }
    C'est en respectant les autres que l'on se fait respecter.

  2. #2
    Membre confirmé
    Homme Profil pro
    Ed Nat
    Inscrit en
    Janvier 2013
    Messages
    325
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Ed Nat
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2013
    Messages : 325
    Points : 559
    Points
    559
    Par défaut
    Bonjour,
    Proposition tardive d'un non spécialiste de Swing (je me cherche déjà des excuses pour les âneries que je pourrais proposer) :

    L'idée est d'interrompre tous les Threads en cours, pour mettre en priorité la mise à jour du label, et de leur redonner la main, une fois la mise à jour effectuée.

    L'interruption est soumise à la variable suspended ajoutée dans la classe Diaporama (déclarée volatile parce que plusieurs thread peuvent y accéder simultanément):

    private boolean volatile suspended;
    On conditionne la poursuite de l'exécution des Threads
    • bouclant sur gestionDonnees
    • mettant à jour l'interface

    en modifiant le corps de ta méthode afficher
    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
    new Thread(new Runnable()
    		{
    			public void run()
    			{
    				for (int i = 1 ; i < gestionDonnees.getNbDonnees() ; i++)
    				{
    					try
    					{
    						Thread.sleep(delai);
    					}
    					catch (InterruptedException e)
    					{
    						// TODO Auto-generated catch block
    						e.printStackTrace();
    					}
    					if (suspended) {
    						synchronized(this) {
    							while (suspended)
    								wait();
    						}
    					}
    					String listeImages = gestionDonnees.getImages(i);
    					String nom = gestionDonnees.getNom(i);
    					final ListeImages images = new ListeImages(nom,listeImages,800);
    					SwingUtilities.invokeLater(new Runnable()
    					{
    						public void run()
    						{
    						if (suspended) {
    							synchronized(this) {
    								while (suspended)
    									wait();
    							}
    						}
    							cartouche.modifieImages(images);
    							cartouche.revalidate();
    						}
    					});
    				}
    			}
     
    		}).start();
    Reste à agir sur la valeur de suspended , (modif qu'il n'y a pas besoin de synchroniser) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    public void actionPerformed(ActionEvent evt)
    {
    	if (evt.getSource().equals(plus)){
    		suspended=true;
    		augmenterDelai();
    		suspended=false;
    }else	if (evt.getSource().equals(moins)){
    		suspended=true;
    		diminuerDelai();
    		suspended=false;
    }
    }
    Bon c'était juste une idée, et je n'ai rien testé.
    Je compte sur les pros de Swing pour me remettre les idées en place si je me suis fourvoyé

  3. #3
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    Encore une erreur à la con. En fait il y avait bien une mise à jour du label mais javais mis delai (qui est en ms) au lieu de delai/1000, du coup le label prenait trop de place et comme mon panel du bas a un FlowLayout, le label n'apparaissait plus.
    C'est en respectant les autres que l'on se fait respecter.

  4. #4
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    Citation Envoyé par kox2ee Voir le message
    Bonjour,
    Proposition tardive d'un non spécialiste de Swing (je me cherche déjà des excuses pour les âneries que je pourrais proposer) :

    L'idée est d'interrompre tous les Threads en cours, pour mettre en priorité la mise à jour du label, et de leur redonner la main, une fois la mise à jour effectuée.

    L'interruption est soumise à la variable suspended ajoutée dans la classe Diaporama (déclarée volatile parce que plusieurs thread peuvent y accéder simultanément):



    On conditionne la poursuite de l'exécution des Threads
    • bouclant sur gestionDonnees
    • mettant à jour l'interface

    en modifiant le corps de ta méthode afficher
    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
    new Thread(new Runnable()
    		{
    			public void run()
    			{
    				for (int i = 1 ; i < gestionDonnees.getNbDonnees() ; i++)
    				{
    					try
    					{
    						Thread.sleep(delai);
    					}
    					catch (InterruptedException e)
    					{
    						// TODO Auto-generated catch block
    						e.printStackTrace();
    					}
    					if (suspended) {
    						synchronized(this) {
    							while (suspended)
    								wait();
    						}
    					}
    					String listeImages = gestionDonnees.getImages(i);
    					String nom = gestionDonnees.getNom(i);
    					final ListeImages images = new ListeImages(nom,listeImages,800);
    					SwingUtilities.invokeLater(new Runnable()
    					{
    						public void run()
    						{
    						if (suspended) {
    							synchronized(this) {
    								while (suspended)
    									wait();
    							}
    						}
    							cartouche.modifieImages(images);
    							cartouche.revalidate();
    						}
    					});
    				}
    			}
     
    		}).start();
    Reste à agir sur la valeur de suspended , (modif qu'il n'y a pas besoin de synchroniser) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    public void actionPerformed(ActionEvent evt)
    {
    	if (evt.getSource().equals(plus)){
    		suspended=true;
    		augmenterDelai();
    		suspended=false;
    }else	if (evt.getSource().equals(moins)){
    		suspended=true;
    		diminuerDelai();
    		suspended=false;
    }
    }
    Bon c'était juste une idée, et je n'ai rien testé.
    Je compte sur les pros de Swing pour me remettre les idées en place si je me suis fourvoyé
    Décidément on a vraiment des idées qui se croisent. C'est justement ce que je viens de mettre en place mais sans le suspended. J'ai utilisé à la place un modifDelai qui est positionné à vrai comme suspended. Et dans la méthode run() du SwingUtilities.invokeLater je teste modifDelai pour commencer par mettre à jour le label avant de passer à l'image suivante.
    En fait avec un label plus court il n'y a aucun problème, je n'ai même pas besoin de ce modifDelai.
    C'est en respectant les autres que l'on se fait respecter.

  5. #5
    Membre confirmé
    Homme Profil pro
    Ed Nat
    Inscrit en
    Janvier 2013
    Messages
    325
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Ed Nat
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2013
    Messages : 325
    Points : 559
    Points
    559
    Par défaut
    C'est pas grave, et c'est plus rassurant que l'erreur vienne de ça...

    Par contre, il est possible que tu aies besoin d'utiliser la suspension, au cas où tu voudrais permettre à l'utilisateur de faire une pause...(je dis ça pour ne pas gâcher mon code ;-))

    Citation Envoyé par Patrice Henrio Voir le message
    Décidément on a vraiment des idées qui se croisent
    Félicitons nous alors !

  6. #6
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    Je continue mon diaporama. J'ai rajouté un bouton run/pause qui comme son nom l'indique lance ou arrête l'affichage . On n'a pas le droit de tuer un Thread par close() donc j'ai essayé de faire comme l'indique le site de Sun.
    J'ai créé un bouton (run_pause) qui réagit en lançant la méthode lancerOuArreter.
    J'ai créé un booléen (run) qui indique si le thread doit être lancé ou suspendu. Au début run vaut false.
    J'ai créé un Thread threadAfficher et une méthode pour le construire. la variable numeroImage indique quelle image est affichée
    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
     
    private void creerThread()
    	{
    		threadAfficher = new Thread(new Runnable()
    		{
    			public void run()
    			{
    				while(run)
    				{
    					numeroImage++;
    					if (numeroImage > gestionDonnees.getNbDonnees()) numeroImage = 0;
    						try
    						{
    							Thread.sleep(delai);
    						}
    						catch (InterruptedException e)
    						{
    							e.printStackTrace();
    						}
    						String listeImages = gestionDonnees.getImages(numeroImage);
    						String nom = gestionDonnees.getNom(numeroImage);
    						final ListeImages images = new ListeImages(nom,listeImages,800);
    						SwingUtilities.invokeLater(new Runnable()
    						{
    							public void run()
    							{
    								cartouche.modifieImages(images);
                                                                        cartouche.revalidate();
    							}
    						});
    				}
    			}
     
    		});
    	}
    L'action déclenchée quand on appuie sur le bouton
    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
     
    	private void arreterOuDemarrer()
    	{
    		run = !run;
    		//on démarre la lecture
    		if (run)
    		{
    			System.out.println("on démarre");
    			System.out.println("Etat " + threadAfficher.getState());
    			System.out.println("vivant " + threadAfficher.isAlive());
    			System.out.println("Interrompu " + threadAfficher.isInterrupted());
    			run_pause.setText("||");
    			if (threadAfficher.getState() == Thread.State.NEW)threadAfficher.start();
    			System.out.println("Etat " + threadAfficher.getState());
    			System.out.println("vivant " + threadAfficher.isAlive());
    			System.out.println("Interrompu " + threadAfficher.isInterrupted());
    		}
    		//on arrête
    		else
    		{
    			System.out.println("on arrète");
    			System.out.println("Etat " + threadAfficher.getState());
    			System.out.println("vivant " + threadAfficher.isAlive());
    			System.out.println("Interrompu " + threadAfficher.isInterrupted());
    			run_pause.setText(">");
    			System.out.println("Etat " + threadAfficher.getState());
    			System.out.println("vivant " + threadAfficher.isAlive());
    			System.out.println("Interrompu " + threadAfficher.isInterrupted());
    		}
    	}
    Les sorties console sont là pour vérifier ce qui se passe. Ca fonctionne sauf que le premier appui sur le bouton lance le thread qui passe de NEW à RUNNABLE, le deuxième le met en état TIMED_WAITING et c'est un troisième appui sur le bouton qui le met en état TERMINATED, alors que je voudrai que le deuxième appui le mette en TERMINATED et le troisième le lance de nouveau.

    1er appui
    on démarre
    Etat NEW
    vivant false
    Interrompu false
    après thread.start()
    Etat RUNNABLE
    vivant true
    Interrompu false
    2ième appui la prise en compte du changement de valeur de run semble immédiate
    on arrète
    Etat TIMED_WAITING
    vivant true
    Interrompu false
    Etat TIMED_WAITING
    vivant true
    Interrompu false
    3ième appui
    on démarre
    Etat TERMINATED
    vivant false
    Interrompu false
    Etat TERMINATED
    vivant false
    Interrompu false
    C'est en respectant les autres que l'on se fait respecter.

  7. #7
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    Citation Envoyé par kox2ee Voir le message
    C'est pas grave, et c'est plus rassurant que l'erreur vienne de ça...

    Par contre, il est possible que tu aies besoin d'utiliser la suspension, au cas où tu voudrais permettre à l'utilisateur de faire une pause...(je dis ça pour ne pas gâcher mon code ;-))


    Félicitons nous alors !
    Justement peux-tu m'expliquer ton code pour l'appliquer au problème que je soulève dans la question suivante.
    En fait voici le comportement que je voudrai avoir.
    l'utilisateur a à sa disposition trois boutons : un bouton de lancement/pause, un bouton précédent et un bouton suivant.
    Lorsque le diaporama est en cours lancement/pause est dans l'état pause pour indiquer qu'un appui dessus mettra le diapo en pause. Lorsque le diaporama est en pause, le bouton lancement/pause est dans l'état lancement.
    Diaporama en cours :
    appui sur lancement/pause : arrêt du diaporama
    appui sur suivant : arrêt du diaporama et passage à la diapo suivante
    appui sur précédent : arrêt du diaporama et passage à la diapo précédente
    Diaporama arrêter
    appui sur lancement/pause : lancement du diaporama
    appui sur suivant : passage à la diapo suivante
    appui sur précédent : passage à la diapo précédente
    C'est en respectant les autres que l'on se fait respecter.

  8. #8
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    Pour ce qui concerne le TIMED_WAITING j'ai compris : c'est que je me trouve dans la temporisation. C'est bien expliqué en français ici : http://www.ukonline.be/programmation...tre3/page1.php
    C'est en respectant les autres que l'on se fait respecter.

  9. #9
    Membre confirmé
    Homme Profil pro
    Ed Nat
    Inscrit en
    Janvier 2013
    Messages
    325
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Ed Nat
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2013
    Messages : 325
    Points : 559
    Points
    559
    Par défaut
    Bonjour,
    je crois que je ferais une classe spécifique (abstraite), implémentant runnable, et permettant de gérer les mécanismes d'interruption, et de mise en attente .
    • Mise en attente avec le wait et notify (et pas comme je l'ai fait)
    • Interruption avec une variable booléenne
    • Munie d'une méthode abstraite (doMyTask) que tu pourras surdéfinir pour y intégrer le déroulement de ton diapo


    Et dans le prog, création d'une instance de la classe abstraite et implémentation de sa méthode doMyTask

  10. #10
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    Citation Envoyé par kox2ee Voir le message
    Bonjour,
    je crois que je ferais une classe spécifique (abstraite), implémentant runnable, et permettant de gérer les mécanismes d'interruption, et de mise en attente .
    • Mise en attente avec le wait et notify (et pas comme je l'ai fait)
    • Interruption avec une variable booléenne
    • Munie d'une méthode abstraite (doMyTask) que tu pourras surdéfinir pour y intégrer le déroulement de ton diapo


    Et dans le prog, création d'une instance de la classe abstraite et implémentation de sa méthode doMyTask
    OK. Merci. Peux-tu me détailler ton idée car j'ai utilisé un exemple d'internet pourcréer ce type de classe et ça n'a pas marché du tout. par contre j'ai essayé autre chose qui marche. Je mets aussi l'explication car je ne suis pas sûr d'avoir bien utilisé les concepts.

    Dans ma classe Diaporama j'ai utilisé un attribut Thread (threadAfficher) et ma méthode arreterOuDemarrer devient.
    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
    	private void arreterOuDemarrer()
    	{
    		run = !run;
    		//on démarre la lecture
    		if (run)
    		{
    			run_pause.setText("||");
    			if (threadAfficher.getState() == Thread.State.NEW) threadAfficher.start();
    		}
    		//on arrête
    		else
    		{
    			threadAfficher.interrupt();
    			threadAfficher = null;
    			creerThread();
    			run_pause.setText(">");
    		}
    	}
    pour la méthode creerThread()
    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
    	private void creerThread()
    	{
    		threadAfficher = new Thread(new Runnable()
    		{
    			public void run()
    			{
    				try
    				{
    					while(!threadAfficher.isInterrupted())
    					{
    						numeroImage++;
    						if (numeroImage > gestionDonnees.getNbDonnees()) numeroImage = 0;
    							Thread.sleep(delai);
    						String listeImages = gestionDonnees.getImages(numeroImage);
    						String nom = gestionDonnees.getNom(numeroImage);
    						final ListeImages images = new ListeImages(nom,listeImages,800);
    						SwingUtilities.invokeLater(new Runnable()
    						{
    							public void run()
    							{
    cartouche.modifieImages(images);
    								cartouche.revalidate();
    							}
    						});
    					}
    				}
    				catch(InterruptedException e){}
    			}
     
    		});
    	}
    Ce code marche mais ce qui m'ennuie c'est de devoir passer le thread à null pour le recréer la ligne d'après. Je ne suis pas sûr que ce soit propre de le recréer sans passer par la ligne threadAfficher = null
    De plus je trouve que mon booléen run fait double emploi avec isAlive et isInterrupted
    Donc je suis preneur d'une autre solution au moins pour progresser dans ce domaine.
    C'est en respectant les autres que l'on se fait respecter.

  11. #11
    Membre confirmé
    Homme Profil pro
    Ed Nat
    Inscrit en
    Janvier 2013
    Messages
    325
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Ed Nat
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2013
    Messages : 325
    Points : 559
    Points
    559
    Par défaut
    Bonjour,
    oui, c'est vrai que les lignes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    threadAfficher = null;
    creerThread();
    semblent peu orthodoxes.

    et que le run fait un peu double emploi avec le isInterrupted...

    Je te mets ce que j'avais en tête tout à l'heure :

    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
     
    public abstract class MyTask implements Runnable {
    	private int delai = 1000;
    	private volatile Thread currentThread = null;
     
    	public void run() {
    		currentThread = Thread.currentThread();
    		while (!currentThread.isInterrupted() && continueCondition()) {
    			doMyTask();
    			try {
    				Thread.sleep(delai);
    			} catch (InterruptedException exception) {
    				onCancelled();
    				break;
    			}
    		}
    	}
     
    	public void cancel() {
    		currentThread.interrupt();
    	}
     
    	public void sleep() {
    		synchronized (this) {
    			try {
    				while (!currentThread.isInterrupted()) {
    					this.wait();
    				}
    			} catch (InterruptedException e) {
    				onCancelled();
    			}
    		}
    	}
     
    	public void wakeUp() {
    		synchronized (this) {
    			this.notify();
    		}
    	}
     
    	public abstract void doMyTask();
     
    	public abstract boolean continueCondition();
     
    	public abstract void onCancelled();
     
    }
    • doMyTask permet d'implémenter ta tâche atomique (1 parcours de la boucle)
    • continueCondition est ta condition de continuité (numeroImage > gestionDonnees.getNbDonnees())
    • onCancelled, la méthode à implémenter en cas d'annulation


    Il y a un seul (gros) problème... mon sleep ne fonctionne pas et fige toute l'application...

  12. #12
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    Regarde ce que j'ai mis dans creerThread() pour que le sleep bloque pas et essaie de l'étendre à ta classe.
    C'est en respectant les autres que l'on se fait respecter.

  13. #13
    Membre confirmé
    Homme Profil pro
    Ed Nat
    Inscrit en
    Janvier 2013
    Messages
    325
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Ed Nat
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2013
    Messages : 325
    Points : 559
    Points
    559
    Par défaut
    L'erreur ne viens pas du sleep de la classe Thread, mais du code de ma méthode sleep...
    Je fais des tests avec une classe plus simple que la tienne (juste une boucle inutile), et j'ai le problème...

    Je te met ma classe de test :
    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
     
    public class TestThreads extends JFrame implements ActionListener {
    	private static final long serialVersionUID = 1L;
    	private JPanel mainPanel;
    	private JButton btStart;
    	private JButton btStop;
    	private JButton btSleep;
    	private JButton btWakeUp;
    	private MyTask mytask;
    	private Thread currentThread;
    	private JLabel lblCompteur;
    	private int compteur = 0;
     
    	public static void main(String[] args) {
    		javax.swing.SwingUtilities.invokeLater(new Runnable() {
    			private TestThreads t;
     
    			@Override
    			public void run() {
    				t = new TestThreads();
     
    			}
    		});
     
    	}
     
    	public TestThreads() {
    		super();
    		// Tâche
    		mytask = new MyTask() {
     
    			@Override
    			public void onCancelled() {
    				compteur = 0;
    				updateLblCompteur();
    			}
     
    			@Override
    			public void doMyTask() {
    				compteur++;
    				updateLblCompteur();
    			};
     
    			@Override
    			public boolean continueCondition() {
    				return compteur < 10000;
    			}
    		};
     
    		// Fenêtre
    		JFrame fen = new JFrame("Test threads");
    		fen.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		fen.setLayout(new BorderLayout());
    		mainPanel = new JPanel(new FlowLayout());
    		lblCompteur = new JLabel("0");
    		mainPanel.add(lblCompteur);
    		btStart = getButton("Start");
    		btStop = getButton("Stop");
    		btSleep = getButton("Sleep");
    		btWakeUp = getButton("Reveil");
    		fen.add(mainPanel, BorderLayout.NORTH);
    		fen.pack();
    		fen.setVisible(true);
    	}
     
    	/**
             * Création d'un bouton
             * 
             * @param text
             * @return
             */
    	private JButton getButton(String text) {
    		JButton bt = new JButton(text);
    		bt.addActionListener(this);
    		mainPanel.add(bt);
    		return bt;
    	}
     
    	private void updateLblCompteur() {
    		SwingUtilities.invokeLater(new Runnable() {
     
    			@Override
    			public void run() {
    				lblCompteur.setText(compteur + "");
     
    			}
    		});
    	}
     
    	@Override
    	public void actionPerformed(ActionEvent e) {
    		if (e.getSource().equals(btStart)) {
    			currentThread = new Thread(mytask);
    			currentThread.start();
    		}
    		if (e.getSource().equals(btStop))
    			mytask.cancel();
    		if (e.getSource().equals(btSleep)) {
    			// Problème !!!!!!!!! Méthode bloquante
    			mytask.sleep();
    		}
    		if (e.getSource().equals(btWakeUp))
    			mytask.wakeUp();
    	}
    }
    Le blocage a lieu ligne 100 (sur le click du bouton sleep), à l'appel de la méthode sleep de la classe MyTask

    La tâche ne s'exécute pas dans l'EDT, ni dans le main Thread, donc je ne vois pas pourquoi ça fige l'application...

    je remet juste l'implémentation de la méthode concernée dans la classe MyTask :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    public void sleep() {
    		synchronized (this) {
    			try {
    				while (!currentThread.isInterrupted()) {
    					this.wait();
    				}
    			} catch (InterruptedException e) {
    				onCancelled();
    			}
    		}
    	}

  14. #14
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    Bon là je vais peut-être dire des conneries mais dans la méthode sleep() que fait excatement this.wait() ? ça n'arrête pas le thread justement ou ça le met seulement en veille ?
    C'est en respectant les autres que l'on se fait respecter.

  15. #15
    Membre confirmé
    Homme Profil pro
    Ed Nat
    Inscrit en
    Janvier 2013
    Messages
    325
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Ed Nat
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Janvier 2013
    Messages : 325
    Points : 559
    Points
    559
    Par défaut
    Citation Envoyé par Patrice Henrio Voir le message
    Bon là je vais peut-être dire des conneries mais dans la méthode sleep() que fait excatement this.wait() ? ça n'arrête pas le thread justement ou ça le met seulement en veille ?
    J'ai délocalisé mon problème de wait dans un nouveau sujet pour te permettre de poursuivre sur ton sujet initial...

  16. #16
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    La partie diaporama est finie et fonctionne exactement comme je veux. Si les codes sont souhaités (ce n'est pas très lourd) je pourrai les fournir.
    C'est en respectant les autres que l'on se fait respecter.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Plusieurs actions possible dans un <form>
    Par lodan dans le forum Balisage (X)HTML et validation W3C
    Réponses: 5
    Dernier message: 18/08/2006, 21h23
  2. Logs SQL des actions réalisées dans Enterprise Manager ?
    Par [DreaMs] dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 11/08/2005, 12h14
  3. [Virtual Pascal] [OWL] Actions clavier dans un dialogue non modal
    Par Alcatîz dans le forum Autres IDE
    Réponses: 3
    Dernier message: 28/07/2005, 11h04
  4. écritures concurrentes dans un fichier
    Par djmalo dans le forum C
    Réponses: 9
    Dernier message: 06/03/2005, 01h45
  5. Réponses: 2
    Dernier message: 03/02/2005, 08h59

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