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