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

wxPython Discussion :

Boucle avec wx.ToggleButton


Sujet :

wxPython

  1. #1
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2012
    Messages : 11
    Par défaut Boucle avec wx.ToggleButton
    Bonjour,

    Je cherche à avoir un bouton "START/STOP" dans une interface wxPython. J'ai choisi pour cela un wx.ToggleButton, qui est bien initialisé et fonctionnel.

    Par contre, quand il est sur la valeur "True" qui correspond pour moi au "START", je dois lancer une routine sans fin.

    Mon but est de pouvoir recliquer sur le bouton pour stopper la routine.

    Mon code non satisfaisant actuel lorsque l'on clique sur le ToggleButton :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    def OnClick(self,event):
    	while self.button.GetValue()==True:
    		# routine
    Je pensais que le bouton serait toujours clickable pendant que cette routine s'exécute mais en fait non. J'ai lu des articles sur les threads, qui semblent être une solution (la seule?) mais je galère pour implémenter le truc.

    Quelqu'un aurait un exemple simple d'utilisation de ToggleButton capable d'exécuter une routine infinie et stoppable en cliquant sur le ToggleButton ?

    Merci d'avance ! :-)

  2. #2
    Membre expérimenté
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    222
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 222
    Par défaut
    Bonjour,

    Il ne faut pas utiliser de while. Essaye plutôt:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    def OnClick(self,event):
    	if self.button.GetValue():
    		# démarrer le thread
            else:
                    #stopper le thread
    Pour les threads va voir ici: http://python.developpez.com/faq/?page=Thread

  3. #3
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2012
    Messages : 11
    Par défaut
    Hello, merci pour la piste.

    Je sens que je me rapproche du but, mais ça plante encore. Voilà ce que j'ai fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    	def OnClick(self,event):
    		self.threadFlag=False
    		if self.button.GetValue()==True:
    			mythread=threading.Thread(target=self.myfunctiontotest)
    			mythread.start()
    		else:
    			self.threadFlag=True
    			mythread.join()
    Dans ma fonction self.myfunctiontotest, j'ai mis :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	def myfunctiontotest(self):
    		while not self.threadFlag:
    suivi du code à exécuter et qui doit boucler genre boucle infinie. A la fin de ce code j'ai mis un time.sleep(0.02)

    Le thread se lance bien, et génère plusieurs de mes résultats, preuve que la boucle se lance. Par contre il plante en l'espace d'un quart de seconde :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Gtk:ERROR:/build/buildd/gtk+2.0-2.24.4/gtk/gtktextlayout.c:1224:get_style: assertion failed: (layout->one_style_cache == NULL)
    Abandon
    Une autre fois ça me donne un "erreur de segmentation" ...

    Une idée ? Mon code est pas bon ? C'est la première fois que je joue avec un thread... Merci d'avance, ça compte beaucoup pour moi :-)

  4. #4
    Membre Expert Avatar de pacificator
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 074
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 074
    Par défaut
    Bonjour,

    j'ai fait un exemple d'application qui permet de compresser des images en utilisant wxpython et des threads: c'est .

  5. #5
    Membre expérimenté
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    222
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 222
    Par défaut
    ça à l'air pas mal (Je suis pas sûr de l'utilité de join()).

    Que fais-tu dans myfunctiontotest. Est que tu modifies des widgets?

  6. #6
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2012
    Messages : 11
    Par défaut
    Citation Envoyé par nyko77 Voir le message
    ça à l'air pas mal (Je suis pas sûr de l'utilité de join()).

    Que fais-tu dans myfunctiontotest. Est que tu modifies des widgets?
    Je génère de la donnée, que j'affiche dans un wx.TextCtrl, dans la même frame. Cela crashe à peu près au bout du 4ème ou 5ème passage dans la boucle de myfunctiontotest

    Par contre en creusant, si je fais la même chose sans modifier ce wx.TextCtrl, genre en affichant tout dans une console avec print, je vois que tout baigne, ma boucle tourne pendant des plombes sans crasher. Par contre quand je clique sur le wx.ToggleButton pour stopper, plantage :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Traceback (most recent call last):
      File "/home/machine/PYTHON/test/testgui.py", line 216, in OnClick
        mythread.join()
    UnboundLocalError: local variable 'mythread' referenced before assignment

  7. #7
    Membre expérimenté
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    222
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 222
    Par défaut
    Ok. C'est bien ce qui me semblait. C'est toujours délicat de modifier un widget à partir d'un thread. Le plus simple est d'utiliser wx.CallAfter:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    wx.CallAfter(myTextCtrl.setValue, "Mon text")
    Pour le ToggleButton, ça parrait plus évident. mythread n'est pas déclarré si self.button.GetValue() == False. Je pense que tu peux enlever la ligne mythread.join().

  8. #8
    Membre Expert Avatar de pacificator
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 074
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 074
    Par défaut
    C'est toujours délicat de modifier un widget à partir d'un thread
    Pas vraiment, il suffit de créer un evenement personnalisé:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (MyEvent, EVT_MY_EVENT) = wx.lib.newevent.NewEvent()
    De le 'binder' dans ta frame:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class MyFrame(wx.Frame):
        .....
        self.Bind(EVT_MY_EVENT, self.OnMyEvent)
    et de poster cet event depuis le thread:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
        evt = MyEvent(arg1 = quelquechose,
            arg2 = autrechose) 
        wx.PostEvent(self.win, evt) # self.win reference la fenêtre parent
    et voilà

  9. #9
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2012
    Messages : 11
    Par défaut
    Citation Envoyé par nyko77 Voir le message
    Ok. C'est bien ce qui me semblait. C'est toujours délicat de modifier un widget à partir d'un thread. Le plus simple est d'utiliser wx.CallAfter:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    wx.CallAfter(myTextCtrl.setValue, "Mon text")
    Pour le ToggleButton, ça parrait plus évident. mythread n'est pas déclarré si self.button.GetValue() == False. Je pense que tu peux enlever la ligne mythread.join().

    Je modifiais le widget comme ça en fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    			self.dialogbox.AppendText(myinfos)
    J'ai essayé du coup :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    			wx.CallAfter(self.dialogbox.AppendText(myinfos))
    Ca plante au bout de 2 ou 3 passages avec l'erreur suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    (python:5063): Gtk-WARNING **: /build/buildd/gtk+2.0-2.24.4/gtk/gtktextview.c:4610: somehow some text lines were modified or scrolling occurred since the last validation of lines on the screen - may be a text widget bug.
    **
    Gtk:ERROR:/build/buildd/gtk+2.0-2.24.4/gtk/gtktextview.c:4611:gtk_text_view_paint: code should not be reached
    Abandon
    et entre chaque passage, cette erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Traceback (most recent call last):
      File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/_core.py", line 14636, in <lambda>
        lambda event: event.callable(*event.args, **event.kw) )
    TypeError: 'NoneType' object is not callable

  10. #10
    Membre expérimenté
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    222
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 222
    Par défaut
    Tu n'utilises pas correctement wx.CallAfter, il faut passer ta valeur en 2ème argument:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    wx.CallAfter(self.dialogbox.AppendText, myinfos)
    Sinon la méthode de pacificator est très bien.

  11. #11
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2012
    Messages : 11
    Par défaut [résolu]
    Citation Envoyé par nyko77 Voir le message
    Tu n'utilises pas correctement wx.CallAfter, il faut passer ta valeur en 2ème argument:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    wx.CallAfter(self.dialogbox.AppendText, myinfos)
    Sinon la méthode de pacificator est très bien.
    Merci à tous les deux, la méthode du wx.CallAfter fonctionne. La méthode de pacificator doit être sympa aussi, mais je suis allé au plus rapide et plus simple pour moi ;-)

    Résolu.

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

Discussions similaires

  1. [DEBUTANT] sortir d'une boucle avec un touche particulière
    Par thibouille dans le forum Débuter
    Réponses: 4
    Dernier message: 25/10/2005, 06h44
  2. Probleme de boucle avec des processus sous UNIX
    Par sebastieng dans le forum POSIX
    Réponses: 6
    Dernier message: 15/10/2005, 18h57
  3. Boucle avec un TIBDataSet
    Par SebCBien dans le forum Bases de données
    Réponses: 4
    Dernier message: 12/09/2004, 17h33
  4. Boucle avec variable à incrémenter
    Par snoop dans le forum Linux
    Réponses: 2
    Dernier message: 19/03/2004, 11h07
  5. boucle avec condition d'arret changeante
    Par NicoH dans le forum Langage
    Réponses: 3
    Dernier message: 10/06/2003, 11h48

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