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 :

Timer : arrêt/relance via bouton


Sujet :

Java

  1. #1
    Membre du Club
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Octobre 2014
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Octobre 2014
    Messages : 99
    Points : 45
    Points
    45
    Par défaut Timer : arrêt/relance via bouton
    Bonjour,

    Je cherche à faire une appli qui effectue une action (ce sera un envoi de commande telnet d'une chaîne de caractere à longueur défini par l'utilisateur) de manière continue, à intervalle défini, et que l'on puisse mettre en pause et relancer via 2 boutons START & STOP.

    J'ai vu qu'il existait pour celà les classes TimerTask et Timer. J'arrive donc à lancer mon action (pour l'exemple je fais juste un println) mais je n'arrive pas à faire fonctionner mes boutons

    Voici mon code :

    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
     
    public class Controleur{
     
    	private MonTimer mt;
    	private String chaine = "abcdefghijklmnopqrstuvwxyz";
     
    	public Controleur() {
    		String input = JOptionPane.showInputDialog("Combien de caracteres ?", 0);
    		int i = Integer.parseInt(input);
    		mt = new MonTimer(i,chaine);
    		mt.scheduleAtFixedRate(mt.getTT(), 0, 2000);
    		JFrame fenetre = new JFrame();
    		JPanel panel = new JPanel();
    		JButton start = new JButton("start");
    		JButton stop = new JButton("stop");
    		start.addActionListener(new Bouton2Listener(mt));
    		stop.addActionListener(new Bouton1Listener(mt));
    		panel.add(start);
    		panel.add(stop);
    		fenetre.setTitle("Network test");
    		fenetre.setResizable(true);
    		fenetre.setLocationRelativeTo(null);
    		fenetre.setContentPane(panel);
    		fenetre.setVisible(true);
    	}
     
    	public static void main(String...args){
    		new Controleur();
    	}
    }
     
    class MonTimer extends Timer{
     
    	int n;
    	String s;
    	TimerTask task;
     
    	public MonTimer(int a, String b){
    		n = a;
    		s = b;	
    		task = new TimerTask(){		
    			public void run(){
    				System.out.println(s.substring(0,n));
    			}
    		};
    	}
     
    	public TimerTask getTT(){
    		return task;
    	}
    }
     
    class Bouton1Listener implements ActionListener{
     
    	MonTimer timer;
     
    	public Bouton1Listener(MonTimer tt){
    		timer = tt;
    	}
     
    	public void actionPerformed(ActionEvent arg0) {
    		try {
    			synchronized(timer){
    				timer.wait();
    			}
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
     
    	}
    }
     
    class Bouton2Listener implements ActionListener{
     
    	MonTimer timer;
     
    	public Bouton2Listener(MonTimer tt){
    		timer = tt;
    	}
     
    	public void actionPerformed(ActionEvent arg0) {
    			synchronized(timer){
    				timer.notify();
    			}	
    	}
    }
    D'abord, je n'avais pas mis les "synchronized" et j'avais une exception IllegalMonitorStateException au clic d'un bouton.

    Maitenant, quand je clique, par exemple sur stop, le bouton reste bloqué enfoncé et ça n'a aucun impact sur mon Timer puisque j'ai toujours des println qui s'affichent...

    Merci d'avance de me sortir de ce pétrin

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

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

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

    La méthode wait() permet d'arrêter le thread qui l'appelle jusqu'à ce qu'un signal soit envoyé par l'appel de la méthode notified() par un autre thread, sur le même objet (la même instance).

    Donc dans ton code, tu dis au thread SWING de s'arrêter en attendand qu'un autre bout de code exécutable uniquement par le thread SWING lui dise de continuer. Autant dire que c'est non seulement impossible, mais en plus, plus rien dans ton interface graphique ne peut fonctionner, puisque le thread SWING (l'Event Dispatch Thread) est en pause.

    Arrête ta tâche avec Timer.cancel() et récréer un Timer, reschedule là pour redémarrer. L'instance de TimerTask étant à part, tu peux gérer des états (éventuellement redéfinir cancel() si tu as besoin de capter l'arrêt).
    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.

  3. #3
    Membre du Club
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Octobre 2014
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Octobre 2014
    Messages : 99
    Points : 45
    Points
    45
    Par défaut
    Alors j'ai à peu près compris ce que tu m'as expliqué mais j'ai toujours un petit problème :

    si je fais le "new" de MonTimer dans Bouton2Listener (pour recréer un Timer comme tu me l'as suggéré), cette objet n'est pas visible par Bouton1Listener et le timer.cancel() me renvoi un NullPointerException ...

    Ou alors je me suis emmélé les pinceaux

    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
     
    public class Controleur{
     
    	private MonTimer mt;
    	private String chaine = "abcdefghijklmnopqrstuvwxyz";
     
    	public Controleur() {
    		String input = JOptionPane.showInputDialog("Combien de caracteres ?", 0);
    		int i = Integer.parseInt(input);
    		JFrame fenetre = new JFrame();
    		JPanel panel = new JPanel();
    		JButton start = new JButton("start");
    		JButton stop = new JButton("stop");
    		start.addActionListener(new Bouton2Listener(mt,i,chaine));
    		stop.addActionListener(new Bouton1Listener(mt));
    		panel.add(start);
    		panel.add(stop);
    		fenetre.setTitle("Network test");
    		fenetre.setResizable(true);
    		fenetre.setLocationRelativeTo(null);
    		fenetre.setContentPane(panel);
    		fenetre.setVisible(true);
    	}
     
    	public static void main(String...args){
    		new Controleur();
    	}
    }
     
    class MonTimer extends Timer{
     
    	int n;
    	String s;
    	TimerTask task;
     
    	public MonTimer(int a, String b){
    		n = a;
    		s = b;	
    		task = new TimerTask(){		
    			public void run(){
    				System.out.println(s.substring(0,n));
    			}
    		};
    	}
     
    	public TimerTask getTT(){
    		return task;
    	}
    }
     
    class Bouton1Listener implements ActionListener{
     
    	MonTimer timer;
     
    	public Bouton1Listener(MonTimer tt){
    		timer = tt;
    	}
     
    	public void actionPerformed(ActionEvent arg0) {
    		timer.cancel(); 
    	}
    }
     
    class Bouton2Listener implements ActionListener{
     
    	MonTimer timer;
            int input;
            String chaine;
     
    	public Bouton2Listener(MonTimer mt,int i,String s){
    		timer = mt;
                    input=i;
                    chaine=s;
    	}
     
    	public void actionPerformed(ActionEvent arg0) {
    			timer = new MonTimer(input,chaine);
                            timer.scheduleAtFixedRate(timer.getTT(),0,2000);	
    	}
    }

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

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

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Qu'est-ce que tu n'a pas bien compris ? La partie sur le wait()/notify() ?

    Il faut bien sûr que la variable de type Timer soit accessible depuis les deux ActionListener. Soit une variable membre de la classe, soit tu te fais une petite classe, qui wrappe un Timer. Et tu fais un code du genre :

    pour start
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if ( timer==null ) {
     
           // créer et scheduler
     
    }
    pour stop
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     if ( timer!=null ) {
     
          // cancel et faire timer=null;
     
    }
    Remarque que tu peux faire ça aussi (le cancel()) avec la TimerTask (et utiliser une seule instance de Timer).

    [EDIT] J'avais pas vu ton code : en fait tu y est presque : il manque juste l'instanciation de mt.

    Où tu peux faire 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
    public class Controleur{
     
    	private MonTimer mt;
    	private String chaine = "abcdefghijklmnopqrstuvwxyz";
     
    	public Controleur() {
    		String input = JOptionPane.showInputDialog("Combien de caracteres ?", 0);
    		int i = Integer.parseInt(input);
    		JFrame fenetre = new JFrame();
    		JPanel panel = new JPanel();
    		JButton start = new JButton("start");
    		JButton stop = new JButton("stop");
     
    		mt = new MonTimer(i,chaine);
     
    		start.addActionListener(new Bouton2Listener(mt));
    		stop.addActionListener(new Bouton1Listener(mt));
    		panel.add(start);
    		panel.add(stop);
    		fenetre.setTitle("Network test");
    		fenetre.setResizable(true);
    		fenetre.setLocationRelativeTo(null);
    		fenetre.setContentPane(panel);
    		fenetre.setVisible(true);
    	}
     
    	public static void main(String...args){
    		new Controleur();
    	}
    }
     
    class MonTimer extends Timer{
     
    	int n;
    	String s;
    	TimerTask task;
     
    	public MonTimer(int a, String b){
    		n = a;
    		s = b;	
    	}
     
    	public void start() {
    		if ( task==null ) {
    			task = new TimerTask(){		
    				public void run(){
    					System.out.println(s.substring(0,n));
    				}
    			};
    			scheduleAtFixedRate(task,0,2000);
    		}
    	}
     
    	public void stop() {
    		if ( task!=null ) {
    			task.cancel();
    			task=null;
    		}
    	}
     
    }
     
    class Bouton1Listener implements ActionListener{
     
    	MonTimer timer;
     
    	public Bouton1Listener(MonTimer tt){
    		timer = tt;
    	}
     
    	public void actionPerformed(ActionEvent arg0) {
    		timer.stop(); 
    	}
    }
     
    class Bouton2Listener implements ActionListener{
     
    	MonTimer timer;
     
    	public Bouton2Listener(MonTimer mt){
    		timer = mt; 
    	}
     
    	public void actionPerformed(ActionEvent arg0) {
     
             timer.start();	
    	}
    }
    Tu peux également mettre les paramètres dans la méthode start(), de manière à pour les changer à chaque start (les paramètres a et b, comme le delay, et la period, aussi).
    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. #5
    Membre du Club
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Octobre 2014
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Octobre 2014
    Messages : 99
    Points : 45
    Points
    45
    Par défaut
    Qu'est-ce que tu n'a pas bien compris ? La partie sur le wait()/notify() ?
    Non, la partie sur les Threads, SWING... J'ai eu très peu de cours là dessus et j'ai du mal à appréhender tout ça. Faudrai que je me penche dessus un peu plus sérieusement mais c'est vrai que l'apprentissage juste en lisant des tutos (sans pouvoir poser de questions), j'ai un peu de mal

    Sinon, merci beaucoup, ça fonctionne nickel !!

  6. #6
    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
    Tout ce qui est exécuté par SWING, que cela soit pour gérer l'affichage (le rafraîchissement de l'affichage, c'est-à-dire ce qui appelle les méthodes paint() des composants), mais également les évènements (tout ce qui est exécuté par dans MouseListener, ActionListener, etc...), ainsi que ce qui est exécuté par un javax.swing.Timer, etc... tout ce qui est exécuté par SWING, donc, (et AWT d'ailleurs sur lequel se fonde SWING) s'exécute dans un unique thread dédié, appelé Event Dispatch Thread (EDT). C'est pourquoi lorsqu'on est dans un autre thread que l'EDT, pour forcer l'exécution d'un code sur l'EDT, on doit appeler SwingUtilities.invokeLater() (ou invokeAndWait()). On le fait pas toujours et ça peut parfois fonctionner sur certains environnements, mais on devrait le faire systématiquement.
    Un thread ne peut exécuter qu'une tâche à fois (une instruction Java exactement), et lorsqu'il est mis en pause, il attend et n'exécute rien. Quand tu appelles wait() dans un code qui est exécuté par l'EDT, ce thread s'arrête et attend qu'on fasse un notify() sur l'instance pour laquelle le wait() a été appelé. Puisqu'il est arrêté, l'interface est gelée : aucun affichage ne se fait (tu vois ce qui a été précédemment affiché, mais si tu essayes de redimensionner la fenêtre par exemple, tu vas avoir des parties qui ne se dessinent plus). C'est pour ça que le bouton "reste enfoncé". En fait, il ne reste pas réellement enfoncé : le thread SWING étant arrêté, il n'exécute pas le code censé redessiner le bouton dans son rendu non enfoncé. De la même façon, tu as beau cliquer partout, il ne se passe rien : parce que des évènements de clic ne sont pas traités.

    Voir

    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.

  7. #7
    Membre du Club
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Octobre 2014
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Octobre 2014
    Messages : 99
    Points : 45
    Points
    45
    Par défaut
    Merci pour cette explication ! tu gères

  8. #8
    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 sebastien4444 Voir le message
    tu gères
    Dans quel état, telle est la question
    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.

  9. #9
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Au fond à droite, bien sûr!

Discussions similaires

  1. Lightwindow via bouton flash
    Par frankychaton dans le forum Flash
    Réponses: 0
    Dernier message: 09/12/2008, 18h01
  2. sous formulaire dans un principal via bouton
    Par tomas dans le forum IHM
    Réponses: 1
    Dernier message: 23/01/2007, 14h59
  3. Réponses: 2
    Dernier message: 22/01/2007, 15h31
  4. boucle jusqu'a arrêt par un bouton
    Par Yepazix dans le forum Langage
    Réponses: 3
    Dernier message: 11/04/2006, 13h11
  5. Réponses: 2
    Dernier message: 15/06/2005, 23h56

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