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 :

Mise à jour Label par une boucle


Sujet :

Tkinter Python

  1. #1
    Membre habitué Avatar de memento80
    Homme Profil pro
    Boulot : ne rentre pas dans une case
    Inscrit en
    Novembre 2004
    Messages
    163
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Boulot : ne rentre pas dans une case
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2004
    Messages : 163
    Points : 125
    Points
    125
    Par défaut Mise à jour Label par une boucle
    Bonjour,

    Je fais mes premiers pas avec tkinter et, autant on trouve plein de tutoriels sur Python, autant on (je ?) ne trouve pas grand chose sur tkinter..

    Du coup, j'ai le problème suivant :

    Je lis un fichier CSV et je voudrais modifier le texte du label pour chaque valeur trouvée. Le rafraichissement du Label sera régulé par une temporisation (sleep).

    Pour l'instant, seul la dernière valeur s'affiche dans le Label en toute fin de programme... mais pas les valeurs intermédiaires.

    Merci par avance pour votre aide.

    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
    from tkinter import *
    import csv
    import time
     
    ficCSV = csv.reader(open("log\\ficCSV.csv", "r"), delimiter=';') # Lecture du fichier csv en direct
     
    class liveFen(object):
        def __init__(self):
            self.root = Tk()
            self.texte = StringVar()
            self.lb1 = Label(self.root, textvariable=self.texte)
            self.lb1.grid(row =2, column =1, columnspan =3)
            Button(self.root, text ="Instruction suivante", command =self.evenSuiv).grid(row =3, column =3)        
            self.root.mainloop()
     
        def evenSuiv(self):
            for ligne in ficCSV: # Pour chaque ligne du fichier
                # Initialisation des variables
                tempsEvenement = float(ligne[0])
                numero = ligne[1]
                typeEvenement = ligne[2]
                commentaireEvenement = ligne[3]
                time.sleep(1.500) # Temps attente
                self.texte.set(commentaireEvenement)
     
    def liveGraph():
        """ Affichage en direct par l'intermédiaire de la lecture d'un fichier csv
        """
        tempsEvenementPrecedent = 0.000
        f = liveFen()

  2. #2
    Membre expérimenté
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    946
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 946
    Points : 1 351
    Points
    1 351
    Par défaut
    Salut,

    C'est vraisemblablement parce que ta boucle prend 100% du temps, donc le rafraichissement graphique ne se fait que quand la CPU est libérée. Il faut donc forcer ce rafraichissement dans ta boucle par la méthode update du widget qui t'intéresse.

    vu ici:

    w.update()

    This method forces the updating of the display. It should be used only if you know what you're doing, since it can lead to unpredictable behavior or looping. It should never be called from an event callback or a function that is called from an event callback.

    A+

    Pfeuh

  3. #3
    Membre habitué Avatar de memento80
    Homme Profil pro
    Boulot : ne rentre pas dans une case
    Inscrit en
    Novembre 2004
    Messages
    163
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Boulot : ne rentre pas dans une case
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2004
    Messages : 163
    Points : 125
    Points
    125
    Par défaut
    Ah oui ça marche maintenant.
    J'ignorais qu'il fallait forcer quoique ce soit, que le rafraichissement se faisait naturellement... C'est moins intuitif du coup pour un novice tel que moi. Il faut juste le savoir.

    Merci beaucoup.

  4. #4
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    En fait on force la mise à jour de l'affichage car l'interpréteur est occupé.
    Une autre approche:
    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
    from tkinter import *
    import csv
     
    class liveFen(object):
        def __init__(self, f, ficCSV):
            self.root = Tk()
            self.fichier = f
            self.ficCSV = ficCSV
            self.lb1 = Label(self.root)
            self.lb1.grid(row=0, column=0, columnspan=3)
            Button(self.root, text="Lire les instructions",
                   command=self.evenSuiv).grid(row=1, column=2)
            self.root.protocol("WM_DELETE_WINDOW", self.on_quit)
            self.root.mainloop()
     
        def evenSuiv(self):
            try:
                ligne = self.ficCSV.__next__()
            except StopIteration:
                self.fichier.close()
                ligne = None
            if ligne:
                # Initialisation des variables
                tempsEvenement = float(ligne[0])
                numero = ligne[1]
                typeEvenement = ligne[2]
                commentaireEvenement = ligne[3]
                self.lb1.config(text = commentaireEvenement)
                #self.root.update()
                self.root.after(1500, self.evenSuiv) # en ms
     
        def on_quit(self):
            self.root.quit()
     
     
    def liveGraph(fichier, ficCSV):
        """ Affichage en direct par l'intermédiaire de la lecture d'un fichier csv
        """
        #tempsEvenementPrecedent = 0.000
        f = liveFen(fichier, ficCSV)
     
    fichier = open("log\\ficCSV.csv", "r")
    ficCSV = csv.reader(fichier, delimiter=';')
    #liveGraph(fichier, ficCSV)
    liveFen(fichier, ficCSV)
    Ou
    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
    from tkinter import *
    import csv
     
    class liveFen(Tk):
        def __init__(self, f, ficCSV):
            Tk.__init__(self)
            self.fichier = f
            self.ficCSV = ficCSV
            self.lb1 = Label(self)
            self.lb1.grid(row=0, column=0, columnspan=3)
            Button(self, text="Lire les instructions",
                   command=self.evenSuiv).grid(row=1, column=2)
            self.protocol("WM_DELETE_WINDOW", self.on_quit)
     
        def evenSuiv(self):
            try:
                ligne = self.ficCSV.__next__()
            except StopIteration:
                self.fichier.close()
                ligne = None
            if ligne:
                # Initialisation des variables
                tempsEvenement = float(ligne[0])
                numero = ligne[1]
                typeEvenement = ligne[2]
                commentaireEvenement = ligne[3]
                self.lb1.config(text = commentaireEvenement)
                #self.update()
                self.after(1500, self.evenSuiv) # en ms
     
        def on_quit(self):
            self.quit()
     
     
    def liveGraph(fichier, ficCSV):
        """ Affichage en direct par l'intermédiaire de la lecture d'un fichier csv
        """
        #tempsEvenementPrecedent = 0.000
        f = liveFen(fichier, ficCSV)
        f.mainloop()
     
    if __name__ == "__main__":
        fichier = open("log\\ficCSV.csv", "r")
        ficCSV = csv.reader(fichier, delimiter=';')
        #liveGraph(fichier, ficCSV)
        app = liveFen(fichier, ficCSV)
        app.mainloop()
    @+
    Merci d'utiliser le forum pour les questions techniques.

  5. #5
    Membre habitué Avatar de memento80
    Homme Profil pro
    Boulot : ne rentre pas dans une case
    Inscrit en
    Novembre 2004
    Messages
    163
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Boulot : ne rentre pas dans une case
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2004
    Messages : 163
    Points : 125
    Points
    125
    Par défaut
    Merci pour cette autre solution PauseKawa. Je n'aurais jamais trouvé ça tout seul.
    Elle m'a solutionné un problème du coup que j'avais : je n'avais plus la main sur la fenêtre quand le "sleep" était en exécution. Maintenant que je l'ai, je peux influencer dessus autant que je veux (accélérer, ralentir...).

    Super. J'ai l'impression que je n'étais pas dans le bon le chemin. Espérons que j'y reste maintenant.

    A+

  6. #6
    Membre habitué Avatar de memento80
    Homme Profil pro
    Boulot : ne rentre pas dans une case
    Inscrit en
    Novembre 2004
    Messages
    163
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Boulot : ne rentre pas dans une case
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2004
    Messages : 163
    Points : 125
    Points
    125
    Par défaut
    Je suis de nouveau coincé sur mon programme lié à la précédente réponse...

    Avec la solution de PauseKawa, je voudrais passer un argument à ma fonction evenSuiv pour, par exemple, en fonction du bouton sur lequel on clique, il choisit de lire un fichier csv différent.

    Et là... je ne trouve pas la méthode.
    J'ai bien passé avec un lambda l'argument au bouton... mais une fois qu'il arrive à la fonction evenSuiv.. dans la fonction, alors j'ai l'impression qu'il se met à boucler (en tout cas, il ne me rends plus du tout le main jusqu'à figer complètement).

    Comment faire ?
    Merci d'avance.

    Code précédent modifié :
    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
    from tkinter import *
    import csv
     
    class liveFen(object):
        def __init__(self, f, ficCSV):
            self.root = Tk()
            self.fichier = f
            self.ficCSV = ficCSV
            self.lb1 = Label(self.root)
            self.lb1.grid(row=0, column=0, columnspan=3)
            Button(self.root, text="Lire les instructions",
                   command=lambda choixFic="A1":self.evenSuiv(choixFic)).grid(row=1, column=2)
            Button(self.root, text="Lire les instructions",
                   command=lambda choixFic="A2":self.evenSuiv(choixFic)).grid(row=2, column=2)
            self.root.protocol("WM_DELETE_WINDOW", self.on_quit)
            self.root.mainloop()
     
        def evenSuiv(self, choixFic):
            try:
                ligne = self.ficCSV.__next__()
            except StopIteration:
                self.fichier.close()
                ligne = None
            if ligne:
                # Initialisation des variables
                tempsEvenement = float(ligne[0])
                numero = ligne[1]
                typeEvenement = ligne[2]
                commentaireEvenement = ligne[3]
                self.lb1.config(text = commentaireEvenement)
                #self.root.update()
                self.root.after(1500, self.evenSuiv(choixFic)) # en ms
     
        def on_quit(self):
            self.root.quit()
     
     
    def liveGraph(fichier, ficCSV):
        """ Affichage en direct par l'intermédiaire de la lecture d'un fichier csv
        """
        #tempsEvenementPrecedent = 0.000
        f = liveFen(fichier, ficCSV)
     
    fichier = open("log\\ficCSV.csv", "r")
    ficCSV = csv.reader(fichier, delimiter=';')
    #liveGraph(fichier, ficCSV)
    liveFen(fichier, ficCSV)

  7. #7
    Membre habitué Avatar de memento80
    Homme Profil pro
    Boulot : ne rentre pas dans une case
    Inscrit en
    Novembre 2004
    Messages
    163
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Boulot : ne rentre pas dans une case
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2004
    Messages : 163
    Points : 125
    Points
    125
    Par défaut
    Quelque chose me dit que j'ai posté trop vite...
    Après avoir repris à tête reposé, il m'a semblé évident d'y mettre la fonction lambda (lambda choixFic="A1":self.evenSuiv(choixFic)) dans la fonction également... et là, miracle ! Ca marche un peu mieux...

    Pourtant il me semblait avoir essayé mais j'ai du me planter dans la syntaxe...
    A suivre... ou pas

  8. #8
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonsoir,

    C'est bien cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    self.root.after(1500, self.evenSuiv(choixFic))
    A la lecture de cette ligne self.evenSuiv(choixFic) est évalué (return None) et evenSuiv() relancé (en dehors du .after() qui correspond lui à self.root.after(1500, None)).
    Cela boucle donc sur la fonction evenSuiv().
    Pire: .after() sans fonction est l'équivalent d'un time.sleep()

    Tkinter.py
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        def after(self, ms, func=None, *args):
            """Call function once after given time.
    
            MS specifies the time in milliseconds. FUNC gives the
            function which shall be called. Additional parameters
            are given as parameters to the function call.  Return
            identifier to cancel scheduling with after_cancel."""
            if not func:
                # I'd rather use time.sleep(ms*0.001)
                self.tk.call('after', ms)

    Vous comprendrez ici que self.root.after(1500, None) fait en plus une pause de 1.5s

    La solution ici c'est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    self.root.after(1500, lambda: self.evenSuiv(choixFic))
    A noter: C'est un cas général pour Python.

    @+
    Merci d'utiliser le forum pour les questions techniques.

  9. #9
    Membre habitué Avatar de memento80
    Homme Profil pro
    Boulot : ne rentre pas dans une case
    Inscrit en
    Novembre 2004
    Messages
    163
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Boulot : ne rentre pas dans une case
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2004
    Messages : 163
    Points : 125
    Points
    125
    Par défaut
    Super. Merci pour l'explication.
    On se sent un peu moins bête que de faire seulement les choses par intuition.

  10. #10
    Nouveau Candidat au Club
    Homme Profil pro
    codeur
    Inscrit en
    Mai 2020
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 20
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : codeur

    Informations forums :
    Inscription : Mai 2020
    Messages : 1
    Points : 1
    Points
    1
    Par défaut boucle label image python
    bonjour j'ai un probleme similaire, j'affiche 10 img a l'écran et j'aimerai les afficher dans une boucle or seul la dernière est afficher meme avec w.update():

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        for i in range(10):
            tempah = Label(buttom_frame,text=str(data['hourly']['temperature_2m'][heure_act + i +24 * jourselect]) +"°C \n" + str(heure_act + i) + "H",bg=couleuract)
            tempah.place(rely=0.8,relx=0.1*i, relwidth=0.1, relheight=0.2)
     
     
            ptitimg0 = PhotoImage(file=str(dic_couleur_fond[sky(jourselect,int(heure_act+i))][2] ), width=125, height=125)
            f0 = Label(buttom_frame, image=ptitimg0,bg =couleuract)
            f0.update()
            f0.place(rely=0.2,relx=0.1*i,relwidth=0.1, relheight=0.6 )
    des idées ?

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 03/10/2013, 10h45
  2. Réponses: 4
    Dernier message: 02/06/2008, 14h03
  3. Requête Mise à jour à partir d'une autre table
    Par temar dans le forum Access
    Réponses: 2
    Dernier message: 17/05/2006, 09h23
  4. Mise à jour automatique d'une table access via un .xls
    Par infratunes dans le forum Access
    Réponses: 4
    Dernier message: 05/04/2006, 18h33
  5. [VS2003][VB.NET]Mise à jour DataSet d'une grille (erreur)
    Par m-mas dans le forum Windows Forms
    Réponses: 2
    Dernier message: 08/02/2006, 10h41

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