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 :

Problème de rafraichissement pendant l'appel d'une fonction


Sujet :

GTK+ avec Python

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 20
    Points : 17
    Points
    17
    Par défaut Problème de rafraichissement pendant l'appel d'une fonction
    Bonjour à tous !!

    je voudrais afficher une progressbar (pulse) pendant l'exécution d'une fonction qui prend du temps...

    J'ai donc parcourue le web et j'ai choisit une solution qui consiste a lancer un thread qui va tourner en même temps que ma fonction. cela fonctionne la progress s'anime si je # l'appel de ma fonction qui dure longtemps...

    J'ai teste aussi le faite que pendant l'exécution de ma fonction qui dure la boucle du thread tourne bien en parallele via un print 'toto' -> OK

    Si j'appel ma fonction qui dure alors là
    pas d'affichage de ma progressbar (qui pourtant et juste avant l'appel de ma fonction) avant la fin de ma fonction qui dure...
    mon code fonctionne mais c'est l'affichage qui n'est pas bon.

    J' ai vu que l'on peu utiliser la fonction pour rafraichir un callback mais je ne trouve pas la manière de l'adapter a mon code et si cela résoudrai mon problème :
    while gtk.events_pending():
    gtk.main_iteration(False)


    voici un extrait de mon code :
    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
    class FractionSetter(threading.Thread):
    	"""This class sets the fraction of the progressbar"""
     
     
    	#Thread event, stops the thread if it is set.
    	stopthread = threading.Event()
     
    	def run(self):
    		"""Run method, this is the code that runs while thread is alive."""
     
    		#Importing the progressbar widget from the global scope
    		global progressbar 
     
    		#While the stopthread event isn't setted, the thread keeps going on
    		while not self.stopthread.isSet() :
    			# Acquiring the gtk global mutex
    			gtk.gdk.threads_enter()
    			#Setting a random value for the fraction
    			progressbar.pulse()
    			# Releasing the gtk global mutex
    			gtk.gdk.threads_leave()
     
    			#Delaying 100ms until the next iteration
    			time.sleep(0.1)
     
     
     
    	def stop(self):
    		"""Stop method, sets the event to terminate the thread's main loop"""
    		self.stopthread.set()
     
     
     
     
     
    gobject.threads_init()
    class window:
     
        # callback pour lancer le traitement depuis une GUI 
        def transfer_put(self, widget):
          self.progressbar.show()
          #Creating and starting the thread
          global fs
          fs = FractionSetter()
          fs.start()
          #fonction qui dure qui dure ...
          self.on_button_clicked_put() 
          #Stopping the thread and the gtk's main loop
          fs.stop()
     
     
     
     
     
        def on_button_clicked_put(self):
         #traitement qui dure longtemps
         for i in liste
          ...
          if ...
    Merci de l'aide que vous pourrez m'apporter.

  2. #2
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2008
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2008
    Messages : 327
    Points : 257
    Points
    257
    Par défaut
    Bonjour,

    J'ai tenté d'analyser votre probleme, mais je n'arrive pas trop à comprendre ce qui ne fonctionne pas...
    D'apres ce que j'ai lu, la progress bar ne s'affiche pas alors que cette derniere se trouve avant le lancement de votre fonction qui dur ?

    Dans le cas ou je ne me serai pas trompé, il faut savoir que les interfaces graphiques fonctionnent de maniere evenementielle, c'est à dire quelles peuvent se (modifier "quand le programme n'est pas utilisé". C'est un peu imagé, mais en gros elle peut pas faire deux choses en meme temps ^^. Dans la fonction, lorsque vous appelle le thread juste avant la boucle for de votre fonction qui prend du temps, il faut lui laisser le temps de s'animer et d'afficher votre progress bar (sa ne marche pas comme les print qui sont instantané).

    Je vous conseille de faire appel a un gobject.idle_add(self.suite), cette fonction a pour avantage d'attendre que le programme soit en attente avant de poursuivre sa tache, exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
    def fonction(self):
        appel du thread
        gobject.idle_add(self.suite)
     
    def suite(self):
        votre fonction qui dure
        return False # <- Tres important pour stopper la fonction
    J'espere que cela vous aidera et tenez moi au courant.

    Bon courage

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 20
    Points : 17
    Points
    17
    Par défaut mieux mais pas encore cela
    Bon j'ai fait ce que tu m'a dit (merci pour ton aide) et maintenant je vois bien la progressbar pendant tout l'appel de la fonction qui dure longtemps mais le pulse de la progressbar ne bouge pas...
    Il est figé !! Ou plûtot l'interface ne se rafraîchit pas d'où l'impression de freeze...
    J'ai mis quelques gtk.main_iteration() dans ma fonction qui dure pour forcer le rafraîchissement de l'interface mais pas de différence...

    petite question :
    Et il possible de rafraîchir l'interface en même temps que le pulse ? Car quand je met ma boucle ci-dessous dans ma class FractionSetter il ne la reconnaît pas (ce qui est normal mais je ne sait pas comment faire pour qu'elle fonctionne dans cette class...

    while gtk.events_pending():
    gtk.main_iteration(False)

  4. #4
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2008
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2008
    Messages : 327
    Points : 257
    Points
    257
    Par défaut
    Bonsoir,

    On va dire que nous sommes sur la bonne voix ^^.
    J'ai juste un doute sur la fonction pulse, ne pourrait-on pas remplacer cette fonction par la fonction "set_pulse_step(fraction)" :

    Dans le thread
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    global progressbar 
    gtk.gdk.threads_enter()
    i = 0
    while i < 1 :
    	progressbar.set_pulse_step(i)
            i = i + 0.1
            print i
            time.sleep(0.1)
    gtk.gdk.threads_leave()
    Ceci permettra de voir si c'est un probleme de thread, de fonction, etc. Si cela ne fonctionne pas avec set_pulse_step, essayez egalement avec set_fraction.

    Bon courage, bonne soirée et peut-etre a tout à l'heure

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 20
    Points : 17
    Points
    17
    Par défaut Bon alors ... le resultat...
    Affichage de la barre de progression vide et le compteur tourne en même temps
    3 tours de compteur

    0.1
    0.2
    0.3
    0.4
    0.5
    0.6
    0.7
    0.8
    0.9
    1.0
    1.1
    0.1
    0.2
    0.3
    0.4
    0.5
    0.6
    0.7
    0.8
    0.9
    1.0
    1.1
    0.1
    0.2
    0.3
    0.4
    0.5
    0.6
    0.7
    0.8
    0.9
    1.0
    1.1

    si je relance une deuxième fois la statusbar et à 100 % mais elle ne bouge pas...
    si je met gtk.main_iteration() dans la fonction qui dure premier lancement la barre de progression + 1 cran sans mouvement et si je relance 100 % sans mouvement.
    le premier code pour le pulse ne fonctionne pas j'ai donc mis (set_fraction)

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 20
    Points : 17
    Points
    17
    Par défaut du nouveau...
    Dans l'appel de ma fonction j'ai rajouté widget que j'avais oublié car présente dans tout les autres fonctions...
    def on_button_clicked_put(self, widget):
    la statusbar s'incrémente bien mais ne s'arrête plus ..
    le compteur tourne sans s'arrêter et ma fonction qui dure longtemps ne fais plus rien...


    si je vire widget comportement du post précédent ou si je garde widget et que j'appel la fonction en lui passant un paramètre supplémentaire car il attend 1 param supplèmentaire du fait du widget -> gobject.idle_add(self.on_button_clicked_put, 1) (pas d'animation mais la fonction qui dure longtemps marche)

    y a un Problème de ce côté la ...

  7. #7
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2008
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2008
    Messages : 327
    Points : 257
    Points
    257
    Par défaut
    Bonjour,

    Bon on est vraiment proche du but, je sais d'ou vient le problème maintenant mais j'avoue que j'ai un doute sur la facon de résoudre cela :s

    Affichage de la barre de progression vide et le compteur tourne en même temps
    3 tours de compteur
    Le compteur tourne, donc le thread fonctionne bien.

    si je relance une deuxième fois la statusbar et à 100 % mais elle ne bouge pas...
    La question qu'il fallait se poser, pourquoi démarre-t-elle à 100 %
    Tout simplement parce que au premier lancement du thread, on lui avait demandé de remplir notre barre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    progressbar.set_pulse_step(i)
    i vallant 1.0 à la fin

    J'en déduit donc, que tout se passe bien... Les fonctions sont bonne et le thread marche, ce qui fouare c'est l'actualisation, même principe qu'avant le thread, le thread ne peut pas modifier l'interface avant d'avoir fini sa boucle... C'est pour sa qu'au deuxieme lancement notre barre est pleine, car a la fin du premier lancement, le thread a fini par actualiser la barre avec 1.0 la remplissant au max.

    Solution :
    J'ai dis que je n'etais pas sur, mais pour ce qui se trouve au dessus, je suis formel ^^.
    J'ai eu une petite idée, le code suivant se trouve dans le thread (pour moi il faut rien changer en dehors)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class FractionSetter(threading.Thread):
            def __init__(self):
                 self.time = 0
     
    	def run(self):
                 gobject.timeout_add(10, self.actualiser)
     
            def actualiser(self):
                 if time > 1:
                     return False # Stopper l'actualisation
                 progressbar.set_pulse_step(self.time)
                 self.time = self.time + 0.1
                 return True # Continuer l'actualisation toutes les 0.1 secondes
    Et une deuxieme version, sur le meme principe :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class FractionSetter(threading.Thread):
            def __init__(self):
                 self.time = 0
     
    	def run(self):
                 while self.time < 1:
                      self.time = self.time + 0.1
                      gobject.idle_add(self.actualiser)
     
            def actualiser(self):
                 progressbar.set_pulse_step(self.time)
                 return False
    Esperons que cette fois, c'est la bonne

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 20
    Points : 17
    Points
    17
    Par défaut ba...
    il y a un problème avec le thread il n'aime pas le __init__

    File "/usr/lib/python2.6/threading.py", line 465, in start
    raise RuntimeError("thread.__init__() not called")
    RuntimeError: thread.__init__() not called

  9. #9
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2008
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2008
    Messages : 327
    Points : 257
    Points
    257
    Par défaut
    Bonjour,

    Autant pour moi, petit oublie ^^ :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class FractionSetter(threading.Thread):
     
            def __init__(self):
                 threading.Thread.__init__(self)
                 self.time = 0
     
    	def run(self):
                  ...
    Bon courage...

    Mickael

    [Edit : 12/12/2010 - 12/13]

    Je viens de trouver une petite fonction qui pourrait bien vous aider, en plus d'utiliser gobject.idle_add... ou à la place, vous pouvez utiliser la fonction :

    Cette dernière force le rafraîchissement de l'interface, et pour cause, voila un exemple très explicite qui colle à votre problème :
    http://python.developpez.com/faq/?page=pyGTK#GTKHelp

    Bon courage...

    Mickael

  10. #10
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 20
    Points : 17
    Points
    17
    Par défaut
    Oui en rajoutant des gtk.main_iteration() l'interface ce rafraîchit correctement et ne freeze plus !!
    Merci pour ton aide et le temps passé sur mon problème...
    Je passe donc le post a résolu

  11. #11
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2008
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2008
    Messages : 327
    Points : 257
    Points
    257
    Par défaut
    Super !!!

    Je pense que je suis aussi content que vous que le problème soit résolu ^^. Si vous avez un autre problème n'hésitez pas à revenir sur le forum

    Bon courage pour la suite...

    Mickael

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

Discussions similaires

  1. problème au niveau de l'appel d'une fonction
    Par kawther dans le forum MATLAB
    Réponses: 2
    Dernier message: 16/06/2009, 20h15
  2. [Système] Problème d'appel d'une fonction
    Par Ministar dans le forum Langage
    Réponses: 8
    Dernier message: 19/09/2006, 22h23
  3. problème avec l'appel d'une fonction
    Par mademoizel dans le forum ASP
    Réponses: 5
    Dernier message: 26/06/2006, 15h04
  4. Réponses: 7
    Dernier message: 12/03/2006, 21h18
  5. Problème de retour aprés l'appel d'une popup
    Par PADAWANN33 dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 06/02/2006, 15h53

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