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

GTK+ avec Python Discussion :

pygtk + threads ; encore eux


Sujet :

GTK+ avec Python

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 17
    Par défaut pygtk + threads ; encore eux
    Bonjour. J'essaye de faire la synthèse de ce que j'ai glané sur la toile à propos de pygtk et les threads. J'essaye donc un programme très simple d'expérimentation. J'ai une classe principale, une qui gère 2 threads et un classe thread proprement dite.

    Mon problème : lorsque les threads 1 et 2 sont lancés simultanément, j'ai toujours un seul des deux labels qui est mis à jour. D'une façon générale, j'ai repéré les fonctions "critiques" avec des flèches, sont-elles aux bons endroits ? Je pense qu'il y a un problème.

    D'avance merci.

    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
     
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
     
    import threading
    import time
    from threads_manager import ThreadsManager
    import gobject
    import gtk
    gobject.threads_init() # <-----
     
    class Main:
     
        def __init__(self):    
            self.window = gtk.Window()
            self.button1 = gtk.Button('Start/stop thread 1')
            self.button2 = gtk.Button('Start/stop thread 2')
            self.label = []
            self.label.append(gtk.Label(str(time.time())))
            self.label.append(gtk.Label(str(time.time())))
            self.table = gtk.Table()
            self.table.attach(self.label[0], 0, 1, 0, 1, xpadding=10)
            self.table.attach(self.button1, 1, 2, 0, 1)
            self.table.attach(self.label[1], 0, 1, 1, 2, xpadding=10)
            self.table.attach(self.button2, 1, 2, 1, 2)
            self.window.add(self.table)
            self.threads_manager = ThreadsManager(self)
            self.button1.connect('clicked', self.threads_manager.switch_thread_state, 1)
            self.button2.connect('clicked', self.threads_manager.switch_thread_state, 2)
            self.window.connect('destroy', self.quit)
            self.window.set_position(gtk.WIN_POS_CENTER)
            self.window.show_all()
     
        def main(self):
            gtk.main()
            return 0
     
        def quit(self, widget_window):
            # À finir. Informer les threads qu'ils doivent stopper afin de quitter proprement ?
            gtk.main_quit()
     
    if __name__ == '__main__':
        main = Main()
        main.main()
    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
     
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
     
    import threading, time
    from my_thread import MyThread
    import gtk
     
    class ThreadsManager:
     
        def __init__(self, main):
            self.main = main
            self.th1 = MyThread(self.main, 1)
            self.th2 = MyThread(self.main, 2)
     
        def switch_thread_state(self, widget_button, nb):
            if nb == 1:
               if self.th1.is_running == True:
                   self.th1.stop()
               else:
                   self.th1.start()
            else: # Therefore nb == 2
                if self.th2.is_running == True:
                   self.th2.stop()      
                else:
                   self.th2.start()
    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
     
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
     
    import threading, time
    import gtk
     
    class MyThread(threading.Thread):
     
        def __init__(self, main, nb):
            threading.Thread.__init__(self)
            self.main = main
            self.nb = nb
            self.is_running = False
     
        def start(self):
            print 'start thread', self.nb
            self.is_running = True
            while self.is_running == True:
                self.update_label()
                time.sleep(0.1) 
     
        def stop(self):
            print 'stop thread', self.nb
            self.is_running = False
     
        def update_label(self):
            # Le but de cette fonction est de montrer comment modifier
            # un objet gtk dans la boucle principale depuis un thread.
            gtk.gdk.threads_enter()  # <-----
            self.main.label[self.nb-1].set_text(str(time.time()))
            gtk.gdk.threads_leave() # <-----
            gtk.main_iteration() # <-----

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 17
    Par défaut Complément
    Je modifie le code précédent. Et maintenant j'utilise la fonction : gobject.idle_add , méthode qui est préférable d'après la FAQ.

    J'ai exactement le même problème, je n'arrive pas à mettre à jour les deux labels en même temps lorsque les deux threads tournent tous les deux (une situation XOR, en quelque sorte).

    J'ai même tenté pour voir de forcer une mise à jour avec un queue_redraw() de la fenêtre principale, dans la boucle while, ça ne change rien. Je commence à sécher, une doc approndie sur gtk et les threads manque vraiment !

    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
    import gobject
    gobject.threads_init() # <-----
    import gtk
     
    class Main:
     
        def __init__(self):    
            self.window = gtk.Window()
            self.button1 = gtk.Button('Start/stop thread 1')
            self.button2 = gtk.Button('Start/stop thread 2')
            self.labels = []
            self.labels.append(gtk.Label('*'))
            self.labels.append(gtk.Label('*'))
            self.table = gtk.Table()
            self.table.attach(self.labels[0], 0, 1, 0, 1, xpadding=10)
            self.table.attach(self.button1, 1, 2, 0, 1)
            self.table.attach(self.labels[1], 0, 1, 1, 2, xpadding=10)
            self.table.attach(self.button2, 1, 2, 1, 2)
            self.window.add(self.table)
            self.threads_manager = ThreadsManager(self)
            self.button1.connect('clicked', self.threads_manager.switch_thread_state, 1)
            self.button2.connect('clicked', self.threads_manager.switch_thread_state, 2)
            self.window.connect('destroy', self.quit)
            self.window.set_position(gtk.WIN_POS_CENTER)
            self.window.show_all()
     
        def main(self):
            gtk.main()
            return 0
     
        def quit(self, widget_window):
            # À finir. Informer les threads qu'ils doivent stopper afin de quitter proprement ?
            gtk.main_quit()
     
    if __name__ == '__main__':
        main = Main()
        main.main()
    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
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
     
    import threading
    from my_thread import MyThread
     
    class ThreadsManager:
     
        def __init__(self, main):
            self.main = main
            self.th1 = MyThread(self.main, 1)
            self.th2 = MyThread(self.main, 2)
     
        def switch_thread_state(self, widget_button, nb):
            if nb == 1:
               if self.th1.is_running == True:
                   self.th1.stop()
               else:
                   self.th1.start()
            else: # Therefore nb == 2
                if self.th2.is_running == True:
                   self.th2.stop()      
                else:
                   self.th2.start()
    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
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
     
    import threading, time
    import gobject
    import gtk
     
    class MyThread(threading.Thread):
     
        def __init__(self, main, nb):
            threading.Thread.__init__(self)
            self.main = main
            self.nb = nb
            self.is_running = False
     
        def start(self):
            print 'start thread', self.nb
            self.is_running = True
            while self.is_running == True:
                gobject.idle_add(self.update_label)
                time.sleep(0.1) 
                gtk.main_iteration() # <-----
     
        def stop(self):
            print 'stop thread', self.nb
            self.is_running = False
     
        def update_label(self):
            # Le but de cette fonction est de montrer comment modifier
            # un objet gtk dans la boucle principale depuis un thread.
            self.main.labels[self.nb-1].set_text(str(time.time()))

  3. #3
    Membre averti
    Inscrit en
    Mars 2010
    Messages
    46
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 46
    Par défaut
    Bjr,
    dans la class MyThread, la fonction doit s'appeler run et non start. iteration inutile.
    gobject.threads_init, uniquement dans le module du thread.

Discussions similaires

  1. boost, la serialization et les threads (encore)
    Par nemodev dans le forum Boost
    Réponses: 5
    Dernier message: 12/03/2010, 15h29
  2. GTK * thread = Encore des problèmes
    Par PhilippeHen dans le forum GTK+ avec C & C++
    Réponses: 14
    Dernier message: 13/08/2009, 11h00
  3. Encore un thread sur "JOGL vs LWJGL"?
    Par v3nu5 dans le forum OpenGL
    Réponses: 4
    Dernier message: 23/04/2009, 15h40
  4. Réponses: 8
    Dernier message: 06/09/2006, 17h36
  5. [C#]Toujours et encore les threads . . .
    Par pierre1256 dans le forum Windows Forms
    Réponses: 5
    Dernier message: 25/05/2006, 13h10

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