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

Python Discussion :

Gestion de l'état des widgets Tkinter par des Threads


Sujet :

Python

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2012
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2012
    Messages : 2
    Points : 1
    Points
    1
    Par défaut Gestion de l'état des widgets Tkinter par des Threads
    Bonjour,
    Je coince actuellement sur un problème avec l'utilisation de Tkinter et des threads.
    Le code ci-après résume mon problème.
    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
     
    import threading
    from Tkinter import *
    import time
     
    class Th(threading.Thread):
        def __init__(self, label):
            threading.Thread.__init__(self)
            self.label = label
            self.index = 0
            self.lock = threading.Lock()
        def run(self):
            while True:            
                self.lock.acquire()
                time.sleep(0.01)
                self.label.config(text=str(self.index))
                self.index += 1
                self.lock.release()
    class App():
        def __init__(self, label):
            self.label = label
        def run(self):
            Th(self.label).start()
            Th(self.label).start()
     
    class Gui():
        def __init__(self):
            gui = Tk()
            label = Label(gui)
            label.pack()
            app = App(label)
            run = Button(gui, text="Run", command=app.run)
            run.pack()
            gui.mainloop()
    Gui()
    Je créé une Gui qui lance une application qui elle-même lance plusieurs threads (ici deux) qui se partagent le même widget tkinter (ici un label) à mettre à jour. Ce code semble fonctionner mais plante au bout d'un certain nombre d'itérations (entre 0 et 10000+).
    Les messages d'erreurs sont:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Exception in thread Thread-1:
    Traceback (most recent call last):
      File "C:\Python27\lib\threading.py", line 552, in __bootstrap_inner
        self.run()
      File "C:\Users\Pierre\workspace\Driver-Events\tests\threadTkinter.py", line 22, in run
        self.label.config(text=str(self.index))
      File "C:\Python27\lib\lib-tk\Tkinter.py", line 1202, in configure
        return self._configure('configure', cnf, kw)
      File "C:\Python27\lib\lib-tk\Tkinter.py", line 1193, in _configure
        self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
    TclError: invalid command name "-text"
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Exception in thread Thread-1:
    Traceback (most recent call last):
      File "C:\Python27\lib\threading.py", line 552, in __bootstrap_inner
        self.run()
      File "C:\Users\Pierre\workspace\Driver-Events\tests\threadTkinter.py", line 22, in run
        self.label.config(text=str(self.index))
      File "C:\Python27\lib\lib-tk\Tkinter.py", line 1202, in configure
        return self._configure('configure', cnf, kw)
      File "C:\Python27\lib\lib-tk\Tkinter.py", line 1193, in _configure
        self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
    TclError: bad option "590": must be cget or configure

    Je souhaiterais votre avis sur ce qui ne vas pas.

  2. #2
    Nouveau Candidat au Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2012
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2012
    Messages : 2
    Points : 1
    Points
    1
    Par défaut
    Il semble qu'il y ait un conflit avec la mainloop de tkinter. Comment peut-on s'en passer?

  3. #3
    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,
    Si vous avez mis un .lock, c'est pour que l'autre thread attende que la séquence, section critique, soit libre.
    Si chaque thread à son .lock, ça ne sert plus à rien.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  4. #4
    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,

    Pareil que wiztrick. Il faut aussi penser à arrêter les threads et empêcher le bouton de les relancer.

    A+

    Pfeuh

    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
     
    import threading
    import Tkinter as tk
    import time
    import random
     
    class Th(threading.Thread):
        def __init__(self, lock, widget):
            threading.Thread.__init__(self)
            self.counter = random.randint(0, 1000000)
            self.lock = lock # le semaphore doit etre partage
            self.widget = widget
            self.running = True # en prevision de l'arret du thread
     
        def run(self):
            while self.running:            
                self.lock.acquire()
                #section supposee critique
                self.widget.config(text=str(self.counter))
                self.counter += 1
                # fin de section critique
                self.lock.release()
                time.sleep(0.001)
     
    class App():
        def __init__(self, win, *widgets):
            self.widgets = widgets
            self.win = win
     
        def run(self, bt):
            # demarre les threads
            threads = []
            lock = threading.Lock()
            for widget in self.widgets:
                item = Th(lock, widget)
                item.start()
                threads.append(item)
            #prepare l'arret de l'application
            command = lambda win=self.win, threads=threads:cleanQuit(win, *threads)
            self.win.protocol("WM_DELETE_WINDOW", command)
            bt['command'] = command
            bt['text'] = 'STOP'
     
    def cleanQuit(win, *threads):
        for item in threads:
            item.running = False
        win.quit()
        print "Bye..."
     
    class Gui():
        def __init__(self):
            gui = tk.Tk()
            widgets = []
            for x in range(5):
                widget = tk.Label(gui)
                widget.pack()
                widgets.append(widget)
            app = App(gui, *widgets)
            bt = tk.Button(gui, text="START", width=10)
            bt['command'] = lambda bt=bt:app.run(bt)
            bt.pack()
            gui.mainloop()
     
    Gui()

Discussions similaires

  1. Réponses: 9
    Dernier message: 27/05/2014, 16h23
  2. Réponses: 2
    Dernier message: 19/01/2012, 15h28
  3. Gestion d'une IHM Tkinter par un thread
    Par Julien38 dans le forum Tkinter
    Réponses: 1
    Dernier message: 23/05/2009, 22h44
  4. Réponses: 2
    Dernier message: 25/02/2007, 23h56
  5. [VBA-E]Remplir des cellules vides par des 0
    Par Tartenpion dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 12/03/2006, 13h58

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