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

Tkinter Python Discussion :

thread, matplotlib, tk canvas


Sujet :

Tkinter Python

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Avril 2009
    Messages : 9
    Points : 6
    Points
    6
    Par défaut thread, matplotlib, tk canvas
    Bonsoir,
    j'écris un programme qui récupère des data et les affiche plus ou moins en temps réel sur un graphe Matplotlib dans un contexte d'interface tkinter. J'ai des problèmes de performance (l'affichage + processing rend l'interface presque inutilisable, la event-loop semble presque toujours bloquée).

    Du coup je veux mettre le processing +graphe dans un thread. Le processing est actuellement mis sous forme de thread et cela fonctionne, mon interface est à nouveau réactive. Mon thread est une boucle infinie avec court un "sleep" au milieu. La fin de la boucle infinie lance la fonction ci-dessous :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
        def updateGraph(self):
            self.ax.cla()
            if hasattr(self, 'data'):
                self.ax.plot(self.time, self.data,'-',color='blue') 
                self.ax.plot(self.time, self.consigne,'-',color='red') 
                minVal =np.amin(self.time)
            else:
                minVal = 0
     
            self.ax.set_xlabel("Temps (s)")
            self.ax.set_ylabel("Vitesse (rd/s)")
            self.ax.set_xlim(left=minVal, right=minVal+self.maxNbPoints*self.deltaTime)
            self.ax.set_ylim(bottom=-0.1, top=5.1)
     #       self.canvas.draw()
    L'objet est un objet "App" Tout fonctionne tant que je ne décomente pas la derniere ligne self.canvas.draw() : sans cette ligne j'ai des résultats de mon processing qui sont les bons. Avec cette ligne, l'application freeze. Notez que le meme code fonctionnait avant d'etre mis sous forme de thread.

    Le graphe lui meme est créé dans le constructeur de mon objet de la façon suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
            self.fig = mplfig.Figure(figsize=(6, 4))  #create figure object
            self.ax = self.fig.add_axes([0.125, 0.125, 0.75, 0.75]) #define axes
            self.canvas = tkagg.FigureCanvasTkAgg(self.fig, master=master)  #encapsulate figure in tkinter canvas
            self.canvas.get_tk_widget().pack(fill=tk.BOTH, expand=1)
    Je pense que ce serait mieux si au lieu d'invoquer canvas.draw() je pouvais envoyer un message à la event_loop pour qu'elle fasse le rafraichissement quand elle peut, mais je n'ai pas trouvé comment faire cela (je débute en python).

    Mon environnement est anaconda, téléchargé avant hier (jour de mes premiers pas émus en python).

    Avez-vous une idée de ce qui peut se passer ?

    Merci !

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Voyez si self.canvas.update_idletasks() peut faire l'affaire à la place de self.canvas.draw().

    Voir la doc ici : http://infohost.nmt.edu/tcc/help/pub...universal.html

    Extrait :

    w.update()

    This method forces the updating of the display. It should be used only if you know what you're doing, since it can lead to unpredictable behavior or looping. It should never be called from an event callback or a function that is called from an event callback.

    w.update_idletasks()

    Some tasks in updating the display, such as resizing and redrawing widgets, are called idle tasks because they are usually deferred until the application has finished handling events and has gone back to the main loop to wait for new events.

    If you want to force the display to be updated before the application next idles, call the w.update_idletasks() method on any widget.
    Notez toutefois que tkinter n'a pas la réputation d'être très thread-friendly.

    @+.

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Avril 2009
    Messages : 9
    Points : 6
    Points
    6
    Par défaut
    Citation Envoyé par tarball69 Voir le message
    Bonjour,

    Voyez si self.canvas.update_idletasks() peut faire l'affaire à la place de self.canvas.draw().

    Voir la doc ici : http://infohost.nmt.edu/tcc/help/pub...universal.html

    Extrait :



    Notez toutefois que tkinter n'a pas la réputation d'être très thread-friendly.

    @+.
    Bonsoir,
    ces méthodes n'existent pas dans un FigureCanvasTkAgg. Bon super, je vais voir si supprimer l'antialias par exemple rend l'application acceptable. Mais le résultat pour moi c'est qu'il ne faut pas utiliser Tkinter, trop limité ...
    Merci !

  4. #4
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par JoeDalton Voir le message
    Bonsoir,
    ces méthodes n'existent pas dans un FigureCanvasTkAgg. Bon super, je vais voir si supprimer l'antialias par exemple rend l'application acceptable. Mais le résultat pour moi c'est qu'il ne faut pas utiliser Tkinter, trop limité ...
    Merci !
    Bonjour,

    En fouillant un peu le net, j'ai trouvé self.canvas.get_tk_widget() => essayez quand même self.canvas.get_tk_widget().update_idletasks() avant de vous décourager, on ne sait jamais.

    @+.

  5. #5
    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 781
    Points
    36 781
    Par défaut
    Salut,

    Citation Envoyé par JoeDalton Voir le message
    Je pense que ce serait mieux si au lieu d'invoquer canvas.draw() je pouvais envoyer un message à la event_loop pour qu'elle fasse le rafraichissement quand elle peut, mais je n'ai pas trouvé comment faire cela (je débute en python).
    essayez de lancer l'exécution de la méthode updateGraph via un <app>.after_idle(<object>.updateGraph).
    A vous de trouvez à quoi raccrocher <app> (l'instance de Tk, d'un widget dans un variable globale), <object> (?).

    Les appels a .update[_idletasks] lancent des "update" dans le contexte du thread appelant.
    Les soumettre via .after_idle va permettre de les exécuter dans le thread du GUI.

    Citation Envoyé par JoeDalton Voir le message
    ...Mais le résultat pour moi c'est qu'il ne faut pas utiliser Tkinter, trop limité ...
    C'est vrai dans l'absolu mais vous auriez ce soucis là avec n'importe quel GUI

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. Réponses: 1
    Dernier message: 10/04/2015, 09h45
  2. [Python 2.X] Matplotlib - canvas refresh
    Par Julien N dans le forum Tkinter
    Réponses: 2
    Dernier message: 23/03/2015, 13h38
  3. Thread, Canvas et Midlet
    Par theserialkiller10 dans le forum Java ME
    Réponses: 0
    Dernier message: 27/03/2009, 01h25
  4. Tri multi-threadé
    Par Tifauv' dans le forum C
    Réponses: 8
    Dernier message: 28/06/2007, 09h00
  5. [Kylix] Pb de Thread !!
    Par Anonymous dans le forum EDI
    Réponses: 1
    Dernier message: 25/04/2002, 13h53

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