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

Tkinter Python Discussion :

Tkinter et arrêter une boucle while - conseils


Sujet :

Tkinter Python

  1. #1
    bm
    bm est déconnecté
    Membre confirmé

    Homme Profil pro
    Freelance
    Inscrit en
    Octobre 2002
    Messages
    874
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Freelance
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2002
    Messages : 874
    Points : 556
    Points
    556
    Billets dans le blog
    6
    Par défaut Tkinter et arrêter une boucle while - conseils
    bonsoir,

    Je ne vois pas comment arrêter une boucle avec un bouton
    quand la boucle est activée :

    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
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    #
     
    from Tkinter import *
    import random
    import time
    import os
     
    def affiche():
        f="Nous sommes le %d/%m/%y, il est %H:%M:%S"
        lbl.config(text=time.strftime(f))
        fenetre.after(500,affiche)
     
    def debut():
        print "Début"
        time.sleep(3)
        prog()
     
    def prog():  
        while True:
            y=random.random()*100
            time.sleep(3)
            print int(y)
     
    def arret():
        print "Arrêt"
        system.exit
     
    fenetre= Tk()
    fenetre.title('Trigger')
    fenetre.geometry("280x140")
    lbl=Label(fenetre,text="heure")
    lbl.place(x=10,y=10)
    b1=Button(fenetre, text="Début",width=20, command=debut)
    b1.place(x=10,y=40)
    b2=Button(fenetre, text="Arrêt",width=20, command=sys.exit)
    b2.place(x=10,y=80)
    photo1=PhotoImage(file="bullet_green.png")
    label1 = Label(image=photo1)
    label1.place(x=220,y=38)
    photo2=PhotoImage(file="bullet_red.png")
    label2 = Label(image=photo2)
    label2.place(x=220,y=78)
    affiche()
    fenetre.mainloop()

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    tkinter est un type de programmation dit événementielle. Vous cliquez sur un bouton çà lance une fonction (appelée callback) et attend que le callback se termine pour traiter l’événement suivant.
    De fait, un code comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    def debut():
        print "Début"
        time.sleep(3)
        prog()
     
    def prog():  
        while True:
            y=random.random()*100
            time.sleep(3)
            print int(y)
    est inadapté à ce type de programmation: si vous voulez que le "callback" se termine au plus tôt, impossible d'attendre avec time.sleep(). Et irréaliste d'avoir une boucle qui ne se termine jamais...

    En plus comme on trouve dans votre code::
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    def affiche():
        f="Nous sommes le %d/%m/%y, il est %H:%M:%S"
        lbl.config(text=time.strftime(f))
        fenetre.after(500,affiche)
    Vous devriez savoir remplacer .sleep par .after.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    bm
    bm est déconnecté
    Membre confirmé

    Homme Profil pro
    Freelance
    Inscrit en
    Octobre 2002
    Messages
    874
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Freelance
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2002
    Messages : 874
    Points : 556
    Points
    556
    Billets dans le blog
    6
    Par défaut
    Irréaliste mais actuel.
    Python sur un système embarqué reçoit en continu les data d'un port série
    avec une boucle while. Et transfère des data dans un fichier.

    Pour ne pas lancer un script en mode console, et laisser la console ouverte.
    Tkinter peut faire tourner cette bouche en tache de fond.

    Si d'autres méthodes sont mieux, lesquelles ?


  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Comme vous avez la solution avec .after, je ne comprends pas trop votre soucis.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    bm
    bm est déconnecté
    Membre confirmé

    Homme Profil pro
    Freelance
    Inscrit en
    Octobre 2002
    Messages
    874
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Freelance
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2002
    Messages : 874
    Points : 556
    Points
    556
    Billets dans le blog
    6
    Par défaut
    Sleep , after .. ??

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    def prog():  
        while True:
            y=random.random()*100
            time.sleep(3)
            print int(y)
    Pourquoi pendant que cette boucle affiche dans la console, le bouton "début"
    reste enfoncé ? Forcer un arrêt est suffisant, mais comment avec un widget bloqué ..

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    b1=Button(fenetre, text="Début",width=20, command=debut)
    b1.place(x=10,y=40)

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Citation Envoyé par bm Voir le message
    Pourquoi pendant que cette boucle affiche dans la console, le bouton "début"
    reste enfoncé ? Forcer un arrêt est suffisant, mais comment avec un widget bloqué ..
    Parce que c'est ainsi que Tkinter (et la plupart des autres bibliothèques graphiques) fonctionnent. Vous trouverez des explications dans ce chapitre du Swinnen.

    Reprenez le callback:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    def affiche():
        f="Nous sommes le %d/%m/%y, il est %H:%M:%S"
        lbl.config(text=time.strftime(f))
        fenetre.after(500,affiche)
    Que faut-il ajouter "autour" pour qu'on puisse arrêter et démarrer la mise à jour de l'horloge?
    Si c'était pour moi, j'écrirai cela ainsi (et sous Python3):
    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
    import tkinter as tk
    import time
     
    class Clock(tk.Label):
        _timer = None
        _ctime = None
     
        def _update(self, delay=200):
            now = time.strftime("%H:%M:%S")
            if self._ctime != now:
                self._ctime = self['text'] = now
            self._timer = self.after(delay,self._update)
     
        def do_start(self):
            if not self._timer:
                self._update()
     
        def do_stop(self):
            if self._timer:
                self.after_cancel(self._timer)
                self['text'] = ''
                self._timer = None
     
        def destroy(self):
            self.do_stop()
            super().destroy()
     
    if __name__ == '__main__':
        root = tk.Tk()
     
        clock = Clock()
        clock.pack()
     
        tk.Button(text='start', command=clock.do_start).pack()
        tk.Button(text='stop', command=clock.do_stop).pack()
        tk.mainloop()
    Mais je ne vais pas passer trop de temps à essayer de vous expliquer le pourquoi et le comment de ces lignes: les tutos sont là pour çà.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    bm
    bm est déconnecté
    Membre confirmé

    Homme Profil pro
    Freelance
    Inscrit en
    Octobre 2002
    Messages
    874
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Freelance
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2002
    Messages : 874
    Points : 556
    Points
    556
    Billets dans le blog
    6
    Par défaut
    ok, merci pour les liens .

    Le but n'est pas d'arrêter une horloge.
    Un événement e1 démarre une boucle , et un autre événement e2
    arrête cette boucle, cela n'est pas possible.

    Je vais voir avec c++ si cela est possible.

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Citation Envoyé par bm Voir le message
    Le but n'est pas d'arrêter une horloge.
    Un événement e1 démarre une boucle , et un autre événement e2
    arrête cette boucle, cela n'est pas possible.
    Pour faire la démo, j'ai utilisé l'horloge du PC.
    Ce qui boucle c'est sa mise à jour.
    Les événements sont déclenchés par les Button "start" et "stop".
    A vous de remplacer l'horloge par la fonction (qui boucle) de votre choix.

    C'est juste une autre façon de répéter périodiquement une séquence d'instruction. Au lieu de "while...sleep()", on re-soumet périodiquement la même fonction. Comme on utilise la boucle d’événement du GUI, çà évite de le bloquer indéfiniment et de pouvoir stopper la chose...

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  9. #9
    bm
    bm est déconnecté
    Membre confirmé

    Homme Profil pro
    Freelance
    Inscrit en
    Octobre 2002
    Messages
    874
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Freelance
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2002
    Messages : 874
    Points : 556
    Points
    556
    Billets dans le blog
    6
    Par défaut
    ok , je n'utilise jamais Tk et Gui.
    J'utilise surtout python en séquentiel avec crontab.

    def destroy ne détruit pas la fenêtre ouverte.

    Je veux modifier le tout avec Swinner et les exo ( j'ai déjà relevé des erreurs
    mineures, gênantes dans ce livre).



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    def destroy(self):
                  exit()

  10. #10
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Citation Envoyé par bm Voir le message
    ok , je n'utilise jamais Tk et Gui.
    J'utilise surtout python en séquentiel avec crontab.
    Relisez le code que vous avez posté, il commence bien par "from Tkinter import *".
    De plus vous avez ouvert cette discussion dans le forum GUI.

    Si vous ne savez pas à quoi cela correspond, pas étonnant que vous ayez des problèmes.
    Mais je ne peux pas apprendre à votre place.
    Désolé.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  11. #11
    bm
    bm est déconnecté
    Membre confirmé

    Homme Profil pro
    Freelance
    Inscrit en
    Octobre 2002
    Messages
    874
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Freelance
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2002
    Messages : 874
    Points : 556
    Points
    556
    Billets dans le blog
    6
    Par défaut
    Vu le nombre de post, c'est un début GUI.
    Et je ne pouvais pas trouver sans votre aide.

    Merci pour le temps passé.
    Il y a trop de façons de coder différentes avec python, ci-dessus la forme Gui Swinner.

    En finalisant avec un titre, c'est la zone text, qui ne s'affiche plus :

    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
    from Tkinter import *
    import time
     
    class Clock():
        _timer = None
        _ctime = None
     
        def _update(self, delay=800):
            now = time.strftime("%H:%M:%S")
            self['text']='(... Reception serie ...)'
            # command serie debut :
     
            # command serie fin :
            if self._ctime != now:
                self._ctime = self['text'] = now
            self._timer = self.after(delay,self._update)
     
        def do_start(self):
            if not self._timer:
                self._update()
     
        def do_stop(self):
            if self._timer:
                self.after_cancel(self._timer)
                self['text'] = '(... Stop ...)'
                self._timer = None
     
        def destroy(self):
            exit()
     
    if __name__ == '__main__':
        root = Tk()
        root.title("Bus")
        clock = Clock()
        Button(text='Debut de trame => (...1...0)', command=clock.do_start).pack()
        Button(text='Fin de trame => (nul..nul)', command=clock.do_stop).pack()
        root.mainloop()

    @+

  12. #12
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Dans ma mouture:
    - "Clock" héritait de Label: c'est ce qui fait que çà affiche quelque chose.
    - j'utilise Python3. çà permet de ne pas surcharger "__init__" et d'utiliser super() sous cette forme là.

    Pour quelle raison devez vous rester sur Python2?

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  13. #13
    bm
    bm est déconnecté
    Membre confirmé

    Homme Profil pro
    Freelance
    Inscrit en
    Octobre 2002
    Messages
    874
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Drôme (Rhône Alpes)

    Informations professionnelles :
    Activité : Freelance
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2002
    Messages : 874
    Points : 556
    Points
    556
    Billets dans le blog
    6
    Par défaut
    Je développe sur syst embarqué avec des moyens réduits (raspberry pi =>raspian qui n'est pas un linux complet).
    Avec GUI et Tkinter, l'éditeur python passe tout en ligne de commande.
    Mais ensuite un 'sudo python lambda.py' sur un fichier ne fonctionne pas.

    Python3 est aussi installé et l'éditeur python plante également sur ce fichier.
    En simulation sur un pc ubuntu tout est 'nickel'
    Je développe en python que la partie acquisition de data, config capteur
    ce qui ne nécessite pas un niveau python important.

    C'est la partie traitement des data , graphisme, page www qui prend plus de temps
    (voir blog du profil)

    Pour corriger l'installation de l'éditeur python quelle partie du forum peut convenir ?

  14. #14
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    J'ai corrigé votre code pour qu'il fonctionne en Python2:
    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
    import Tkinter as tk
    import time
     
    class Clock(tk.Label):
        _timer = None
        _ctime = None
     
        def __init__(self, *args, **kwds):
            tk.Label.__init__(self, *args, **kwds)
     
        def _update(self, delay=800):
            now = time.strftime("%H:%M:%S")
            self['text']='(... Reception serie ...)'
            # command serie debut :
     
            # command serie fin :
            if self._ctime != now:
                self._ctime = self['text'] = now
            self._timer = self.after(delay,self._update)
     
        def do_start(self):
            if not self._timer:
                self._update()
     
        def do_stop(self):
            if self._timer:
                self.after_cancel(self._timer)
                self['text'] = '(... Stop ...)'
                self._timer = None
     
        def destroy(self):
            self.do_stop()
            tk.Label.destroy(self)
     
    if __name__ == '__main__':
        root = tk.Tk()
        root.title("Bus")
        clock = Clock()
        clock.pack()
        tk.Button(text='Debut de trame => (...1...0)', command=clock.do_start).pack()
        tk.Button(text='Fin de trame => (nul..nul)', command=clock.do_stop).pack()
        tk.mainloop()
    Pour corriger l'installation de l'éditeur python quelle partie du forum peut convenir ?
    Suivant l'éditeur que vous utilisez, je mettrais çà dans les forums "EDI/RAD" ou "General Python"

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

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

Discussions similaires

  1. Arrêter une boucle while
    Par nanou2183 dans le forum Macro
    Réponses: 2
    Dernier message: 02/03/2012, 12h01
  2. Arrêter une boucle (while) en cours d'exécution
    Par Cybberdupont dans le forum Langage
    Réponses: 19
    Dernier message: 26/06/2008, 14h24
  3. [Tkinter] Méthode get() dans une boucle while
    Par Thundie dans le forum Tkinter
    Réponses: 2
    Dernier message: 04/02/2006, 00h06
  4. Réponses: 6
    Dernier message: 17/06/2005, 16h51
  5. [MFC] Dialog dans une boucle while
    Par oxor3 dans le forum MFC
    Réponses: 5
    Dernier message: 23/04/2004, 22h51

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