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

GUI Python Discussion :

Rafraîchir un label dans une fenêtre (Tkinter) créée dans un Thread


Sujet :

GUI Python

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Personnel de direction de l'éducation nationale
    Inscrit en
    Octobre 2018
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Personnel de direction de l'éducation nationale
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2018
    Messages : 3
    Points : 1
    Points
    1
    Par défaut Rafraîchir un label dans une fenêtre (Tkinter) créée dans un Thread
    Bonjour à toutes et à tous,
    Peut être, avant d'entrer dans le vif du sujet, une petite présentation car je suis nouveau sur ce forum.
    Vous pouvez m'appeler Sam et je ne suis plus tout jeune (mon premier ordinateur était un commodore 64)
    J'ai fait de la programmation dans ma jeunesse (sur le commodore 64, puis sur un Atari 1024 STF, puis Basic, Pascal, Turbo C, C++, Delphi, Visual Basic, et même en LSE pour ceux qui connaissent) et j'ai même eu un diplôme universitaire pour ça (en C++).
    Mais j'ai choisi de travailler dans un autre domaine et j'ai continué de programmer à mes heures perdues. Force est de constater que quand on ne pratique pas régulièrement, on oubli rapidement...
    Aujourd'hui j'ai décidé de revenir à mes première amours, mais le langage à changer et les concepts aussi...

    Je travaille sur un Raspberry Pi 2 couplé à un module GPS.
    Pas de problème particulier, je récupère bien les informations du GPS.
    La où ça coince, c'est quand je veux afficher ces données dans une fenêtre créée avec Tkinter
    J'utilise 2 Threads :
    - un qui lit les données GPS en permanence (Celui là je l'ai chopé sur le Net)
    - un autre pour afficher la fenêtre (Je me suis dit que ce serait un bon exercice pour comprendre les threads et se remettre dans le bain)

    Mon code est le suivant :

    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
     
    #! /usr/bin/python
    # -*- coding: utf-8 -*-
    # Written by Dan Mandle http://dan.mandle.me September 2012
    # License: GPL 2.0
     
    #Importation des differentes librairies
    from gps import *
    from Tkinter import *
    import threading
    #import os
    #from time import *
    #import time
     
    gpsd = None #Initialise la variable globale
     
    def FIN(): #Definition de la fonction FIN
        gpsp.running = False #stop le thread gpsp
        fen.running = False #stop le thread fen
        gpsp.join() #attend la fin du thread gpsp
        fen.join() #attends la fin du thread fen    
     
    class GpsPoller(threading.Thread):
      def __init__(self):
        threading.Thread.__init__(self)
        global gpsd #donne acces à la variable global gpsp
        gpsd = gps(mode=WATCH_ENABLE) #commence la collect des données du GPS
        self.current_value = None
        self.running = True #setting the thread running to true
     
      def run(self):
        global gpsd
        while gpsp.running:
            gpsd.next() #this will continue to loop and grab EACH set of gpsd info to clear the buffer
            print '1' #Affiche un 1 pour voir si le thread fonctionne
     
     
     
    class Window(threading.Thread):
        def __init__(self):
            threading.Thread.__init__ (self)
            self.current_value = None
            self.running = True
     
        def run (self):
            Fenetre=Tk() #Création de la fenetre
            Fenetre.geometry("300x100") #Defini la taille de la fenetre
            Fenetre.title ('Coordonnées GPS') #Définition du titre de la fenêtre
     
            VarLatitude=gpsd.fix.latitude #Acquisition de la Latitude
            VarLongitude=gpsd.fix.longitude #Acquisition de la Longitude
            VarTime=gpsd.utc #Acquisition de l'heure UTC
     
            TextLatitude=Label(Fenetre, text='Latitude    : ' +str(VarLatitude)) #Création du Label Latitude
            TextLatitude.pack(side = TOP) #Positionnement
     
            TextLongitude=Label(Fenetre, text='Longitude    : '+str(VarLongitude)) #Création du Label Longitude
            TextLongitude.pack(side = TOP) #Positionnement
     
            TextTime=Label(Fenetre, text='Heure : '+str(VarTime)) #Création du Label Time
            TextTime.pack(side = TOP) #Positionnement
     
            Button2=Button(Fenetre, text='FIN', command=FIN) #Création du bouton FIN
            Button2.pack(side = BOTTOM) #Positionnement
     
            while True:
                VarLatitude=gpsd.fix.latitude #Acquisition de la Latitude
                VarLongitude=gpsd.fix.longitude #Acquisition de la Longitude
                VarTime=gpsd.utc #Acquisition de l'heure UTC
     
                TextLatitude.configure(text='Latitude    : ' +str(VarLatitude)) #MAJ du Label Latitude
     
                TextLongitude.configure(text='Longitude    : '+str(VarLongitude)) #MAJ du Label Longitude
     
                TextTime.configure(text='Heure : '+str(VarTime)) #MAJ du Label Time
     
                print '2' #Affiche un 2 pour voir si le thread fonctionne
     
    #C'est la que ca coince
    #Quand Fenetre.update_idletasks() est actif, le bouton FIN ne repond pas MAIS les données GPS sont MAJ
    #Quand Fenetre.mainloop() est actif, le bouton FIN répond MAIS les données GPS ne sont pas MAJ
     
                #Fenetre.mainloop() #Activation de la Fenetre
                Fenetre.update_idletasks()
     
    #Fin du problème
     
     
    # Main Program
    if __name__ == '__main__':
     
        gpsp = GpsPoller() #Creation du thread GPS
        fen = Window() #Creation du thread de la fenetre
        gpsp.start() #Lancement du thread gpsp
        fen.start() #Lancement du thread fen
    Si vous lisez cette ligne cette ligne, c'est que peut être que mon code n'est pas si imbuvable que ça...
    En résumé, mon problème est le suivant :
    Soit les données GPS se mettent à jour dans la fenêtre, mais je ne peux pas quitter le programme avec le bouton FIN, soit je peux quitter le programme avec le bouton FIN (il y a une erreur en sortie, mais pour l'instant c'est un point de détail), mais les données GPS ne se mettent pas à jour.
    Je vois bien la différence qu'il y a entre ".mainloop()" et ".update_idletasks()". Le premier "lit" les événements et donc le bouton FIN est opérationnel, le second met à jour la fenêtre et ses différents éléments mais n'est pas à l'écoute des événements. Et pour autant, je n'arrive pas à m'en sortir.
    Je ne vous cacherai pas que je ne suis pas très à l'aise avec les termes modernes tels que "classe", "instance", "widget". Mais je suis prêts à m'y mettre si quelqu'un peut me l'expliquer simplement...

    Quoi qu'il en soit, si l'un ou l'une de vous avez une solution à m'apporter, je suis preneur.

    Un grand merci à vous pour m'avoir lu jusqu'à la dernière ligne, et peut être qu'un jour je pourrai vous renvoyer la pareil

    Sam

  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,

    Citation Envoyé par SamFisher69 Voir le message
    La où ça coince, c'est quand je veux afficher ces données dans une fenêtre créée avec Tkinter
    J'utilise 2 Threads :
    - un qui lit les données GPS en permanence (Celui là je l'ai chopé sur le Net)
    - un autre pour afficher la fenêtre (Je me suis dit que ce serait un bon exercice pour comprendre les threads et se remettre dans le bain)
    Le GUI doit être dans le thread principal (et les versions récentes de Python vous sortiraient un message d'erreur si ce n'est pas le cas).
    Un GUI est déjà un mécanisme de threading dit coopératif (les threads de Threading sont un mécanisme pré-emptif). Pour tkinter, çà passe par .after.

    Citation Envoyé par SamFisher69 Voir le message
    Je ne vous cacherai pas que je ne suis pas très à l'aise avec les termes modernes tels que "classe", "instance", "widget". Mais je suis prêts à m'y mettre si quelqu'un peut me l'expliquer simplement...
    Il y a de bons tutos pour çà!
    Et une meilleure connaissance des fonctionnalités de tkinter vous permettrait de coder çà bien plus simplement (et de vous apercevoir que vous n'avez pas vraiment besoin de connaître "class" et "instance" pour coder une petite application).

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

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    Personnel de direction de l'éducation nationale
    Inscrit en
    Octobre 2018
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Personnel de direction de l'éducation nationale
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2018
    Messages : 3
    Points : 1
    Points
    1
    Par défaut
    Bonjour Wiztricks et merci pour cette réponse rapide.

    Je ne suis pas certain d'avoir tout compris, mais je vais me pencher sur ".after". Le livre que j'utilise (Apprendre à programmer python de Gérard Swinnen) y fait référence. Cela devrait aider.
    Pour ce qui est des tutos, auriez vous un lien à me conseiller ?

    Et encore merci pour votre aide.

    Sam

  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,

    Citation Envoyé par SamFisher69 Voir le message
    Pour ce qui est des tutos, auriez vous un lien à me conseiller ?
    Le Swinnen est très bien.
    Vous avez une mine de tutoriel ici.

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

  5. #5
    Nouveau Candidat au Club
    Homme Profil pro
    Personnel de direction de l'éducation nationale
    Inscrit en
    Octobre 2018
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Personnel de direction de l'éducation nationale
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2018
    Messages : 3
    Points : 1
    Points
    1
    Par défaut
    Wiztricks,

    Par pure vanité et aussi par fierté, voici le code que vos conseils m'ont inspiré :

    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
     
    #! /usr/bin/python
    # -*- coding: utf-8 -*-
    # Written by Dan Mandle http://dan.mandle.me September 2012
    # License: GPL 2.0
     
    #Importation des differentes librairies
    from gps import *
    from Tkinter import *
    import threading
    from time import *
    import time
    import os
     
    gpsd = None #Initialise la variable globale
     
    #=========Definition du Thread du GPS=======
     
    class GpsPoller(threading.Thread):
      def __init__(self):
        threading.Thread.__init__(self)
        global gpsd #donne acces à la variable global gpsp
        gpsd = gps(mode=WATCH_ENABLE) #commence la collect des données du GPS
        self.current_value = None
        self.running = True #setting the thread running to true
     
      def run(self):
        global gpsd
        while gpsp.running:
            gpsd.next() #this will continue to loop and grab EACH set of gpsd info to clear the buffer
            print 'GPS Fonctionne' #Affiche un 1 pour voir si le thread fonctionne
     
    #========Fin de la definition du Thread du GPS=======
     
    #=========Definition des fonctions
     
    def MAJ():
        global Flag, VarLatitude, VarLongitude, VarTime #Rend ces variables globales visibles
     
        VarLatitude=gpsd.fix.latitude #Acquisition de la Latitude
        VarLongitude=gpsd.fix.longitude #Acquisition de la Longitude
        VarTime=gpsd.utc #Acquisition de l'heure UTC
     
        TextLatitude.configure(text='Latitude    : ' +str(VarLatitude)) #MAJ du Label Latitude
     
        TextLongitude.configure(text='Longitude    : '+str(VarLongitude)) #MAJ du Label Longitude
     
        TextTime.configure(text='Heure : '+str(VarTime)) #MAJ du Label Time
     
        print 'MAJ Fonctionne' #Affiche un 2 pour voir si le pseudo-thread fonctionne
     
        if Flag > 0: #Si la variable Flag est > à 0
            Fenetre.after(100, MAJ) #On fait de la recursivite, la fonction s'appelle elle meme pour continuer la MAJ
     
    def Quitter():
        gpsp.running = False #Arret du Thread gpsp
        gpsp.join() #Attend la fin du Thread gpsp
        Fenetre.destroy() #Ferme la fenetre et le programme
     
     
    def Start_it():
        global Flag #Rend la variable globale visible
        if Flag == 0:
            Flag = 1 #Attribue la valeur 1 à la variable Flag
            MAJ() #Appel la fonction MAJ
     
    def Stop_it():
        global Flag #Rend la variable blobale visible
        Flag=0 #Attribue la valeur 0 à la variable Flag
     
     
    #=========Programme principal==========
     
    #--definition des variables globales--
    Flag = 0 #Variable global flag pour sortir d'une boucle
    VarLatitude = 0 #Variable pour la Latitude
    VarLongitude = 0 #Variable pour la Longitude
    VarTime = 0 #Variable pour l'heure
     
    #=========Creation du Thread GPS et lancement du Thread GPS
    gpsp = GpsPoller()
    gpsp.start()
     
    #=========Création de la fenetre=======
    Fenetre=Tk() #Création de la fenetre
    Fenetre.geometry("300x100") #Defini la taille de la fenetre
    Fenetre.title ('Coordonnées GPS') #Définition du titre de la fenêtre
     
    VarLatitude=gpsd.fix.latitude #Acquisition de la Latitude
    VarLongitude=gpsd.fix.longitude #Acquisition de la Longitude
    VarTime=gpsd.utc #Acquisition de l'heure UTC
     
    TextLatitude=Label(Fenetre, text='Latitude    : ' +str(VarLatitude)) #Création du Label Latitude
    TextLatitude.pack(side = TOP) #Positionnement
     
    TextLongitude=Label(Fenetre, text='Longitude    : '+str(VarLongitude)) #Création du Label Longitude
    TextLongitude.pack(side = TOP) #Positionnement
     
    TextTime=Label(Fenetre, text='Heure : '+str(VarTime)) #Création du Label Time
    TextTime.pack(side = TOP) #Positionnement
     
    Button1=Button(Fenetre, text='Commencer MAJ', command=Start_it)
    Button1.pack(side = LEFT)
     
    Button2=Button(Fenetre, text='Fin MAJ', command=Stop_it) #Création du bouton FIN
    Button2.pack(side = LEFT) #Positionnement
     
    Button3=Button(Fenetre, text='Quitter', command=Quitter) #Creation du bouton QUITTER
    Button3.pack(side=RIGHT) #Positionnement
     
    #========Boucle principale========
    Fenetre.mainloop()
    Ça fonctionne parfaitement ! Je vais enfin pouvoir dormir sereinement...
    Je ne suis pas satisfait de la position des boutons, mais pour l'instant, je m'en contenterai.
    Je peux maintenant passer à la phase suivante : afficher une carte, et positionner un point en fonction des coordonnées reçues par le GPS.

    Merci beaucoup pour votre aide.

    Sam

Discussions similaires

  1. [Python 3.X] Variable dans une fenêtre Tkinter
    Par wazo_qui_vole dans le forum Tkinter
    Réponses: 12
    Dernier message: 27/05/2018, 21h21
  2. [Python 3.X] Variable dans une fenêtre Tkinter
    Par wazo_qui_vole dans le forum Général Python
    Réponses: 5
    Dernier message: 26/05/2018, 16h30
  3. Réponses: 2
    Dernier message: 31/08/2017, 17h43
  4. Réponses: 14
    Dernier message: 02/07/2007, 09h30
  5. Réponses: 2
    Dernier message: 07/08/2006, 22h36

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