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 :

répéter une action en boucle


Sujet :

Tkinter Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2010
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2010
    Messages : 147
    Par défaut répéter une action en boucle
    Bonjour,
    Je cherche à faire une coloration <<presque>> automatique du contenu du widget Text. Ce que j'aimerais, c'est que la commande syntaxe_couleur s'exécute toutes les 5 secondes par exemple mais ne m'empêche de continuer à écrire dans le widget Text.
    Suis-je obligé de passer par un thread? où y a-t-il une solution?
    Merci pour vos réponses;
    Gabriel
    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
    import tkinter
    import time
     
    def syntaxe_couleur(event=None):
        time.sleep(5)
        contents = t.get(1.0, tkinter.END)
        coordonnees=t.index(tkinter.INSERT) 
        t.delete("1.0",tkinter.END)
        t.insert("1.0",contents)
        t.mark_set(tkinter.INSERT, coordonnees)
        t.see(coordonnees)      
     
        nmbChar = tkinter.IntVar()
        lastPos = "1.0"
        while 1 :
                liste_noms="[0-9]"
                lastPos = t.search(liste_noms, index = lastPos, stopindex = tkinter.END, regexp = 1, count = nmbChar )
                if lastPos == "" :
                    break
                t.tag_add( 'commandes', lastPos, "%s + %d chars" % ( lastPos, nmbChar.get() )  )
                lastPos = "%s + 1 chars" % lastPos
        t.tag_configure( 'commandes', foreground = 'red',font=("courier",10))
     
    root=tkinter.Tk()
    t=tkinter.Text(root)
    t.focus_set()
    t.pack()
    t.bind('<Control-m>',syntaxe_couleur)
    root.mainloop()

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 754
    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 754
    Par défaut
    Salut,

    Tk comme la plupart des GUI sont dits "event driven". En gros cela signifie que les "changements" de l'affichage et l'appel des fonctions associées au widgets affichés, au keyboard ou à la souris sont "evènements qui déclenchent l'appel à".

    Pour des raisons techniques, difficile de lancer "l'appel à" "dès que" car l'action déclenchée par un événement précédent est peut être encore "active". La machine va assez vite pour que lorsque vous cliquez çà réagisse mais impossible qu'elle oublie que vous avez cliqué parce que l'action précédente n'est pas encore terminée => naturellement, on empile les événements dans une liste et ils sont traités séquentiellement.

    => lorsqu'après avoir construit l'affichage on appelle .mainloop, on démarre la boucle de traitement de la liste d'évènements.

    Avec toute cette infrastructure, il est peux couteux de permettre au programmeur d'insérer ses propres évènements dans la "mainloop".

    Dans votre cas t.after ( 5000, syntaxe_couleur ) avec un repost de la même chose en sortie de syntaxe_couleur devrait suffire.

    Suis-je obligé de passer par un thread? où y a-t-il une solution?
    Comme syntaxe_couleur modifie l'état du widget text, vous ne pouvez pas passer par un thread!!!
    Relisez le paragraphe "Pour des raisons techniques" précédent: Si le GUI a été construit pour traiter les événements séquentiellement, c'est pour assurer, garantir la cohérence de son "état global".
    Avec l'exécution de syntaxe_couleur dans un thread diffférent de celle du GUI, vous ne pouvez plus assurer cette cohérence => bug.
    Note: Vous pouvez utiliser des threads, mais lorsque la thread doit parler avec le GUI, elle devra elle aussi "poster" un évènement i.e appeler .after_idle ou .after(0,...)

    Questions:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    contents = t.get(1.0, tkinter.END)
        coordonnees=t.index(tkinter.INSERT) 
        t.delete("1.0",tkinter.END)
        t.insert("1.0",contents)
        t.mark_set(tkinter.INSERT, coordonnees)
        t.see(coordonnees)
    Intuitivement, la mise en forme n'est importante que pour ce que l'utilisateur "voit" i.e. la partie affichée du texte qui n'en est qu'un sous ensemble.
    Il serait peut être "utile" de penser à séparer le bout de texte qu'on voit du texte sauvé dans le fichier.

    Je n'aime pas l'idée "toutes les 5s...": pourquoi ne pas faire cela au fur et à mesure que le texte est modifié?

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

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2010
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2010
    Messages : 147
    Par défaut
    Bonsoir,

    Je commence par répondre par le plus facile:
    Je n'aime pas l'idée "toutes les 5s...": pourquoi ne pas faire cela au fur et à mesure que le texte est modifié?
    En fait, il y a deux raisons - qui ne sont peut être pas valables... -
    Je pense que mon programme de coloration synthétique n'est pas performant (dans le code ci-dessus, il n'y avait qu'un bout). J'avais commencé par faire un root.bind('<KeyPress>',syntaxe_couleur) mais j'ai remarqué à l'usage, que le traitement pouvait s'avérer long (presque 1s) lorsque le fichier devient lourd ce qui est gênant lorsque l'on tape son texte...
    La deuxième raison, c'est que j'ai déjà <<réservé>> le '<keypress>' pour une complémentation automatique et je crains (peut-être à tort) qu'il y ait un <<conflit>> d'actions déclenchées par la même touche.
    Le sous programme complet pour la coloration de syntaxe est 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
    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
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
        def syntaxe_couleur(self,event=None):
            id_onglet = self.ong.select()
            texte1 = self.fe.feuilles[id_onglet][1]
            contents = texte1.get(1.0, tkinter.END)
            coordonnees=texte1.index(tkinter.INSERT) 
            texte1.delete("1.0",tkinter.END)
            texte1.insert("1.0",contents)
            texte1.mark_set(tkinter.INSERT, coordonnees)
            texte1.see(coordonnees)      
     
            nmbChar = tkinter.IntVar()
            lastPos = "1.0"
            while 1 :
                  liste_noms="(\\\\)([a-zA-Z0-9]*)([\\\\+=\(\{\$\-&\\n\ \}\)\[\]_\^,?;.:/%])"
                  lastPos = texte1.search(liste_noms, index = lastPos, stopindex = tkinter.END, regexp = 1, count = nmbChar )
                  if lastPos == "" :
                        break
                  texte1.tag_add( 'commandes', lastPos, "%s + %d chars" % ( lastPos, nmbChar.get() )  )
                  lastPos = "%s + 1 chars" % lastPos
            texte1.tag_configure( 'commandes', foreground = 'brown',font=("courier",10))
            lastPos = "1.0"
            while 1 :
                  liste_noms="(\\\\begin)|(\\\\end)|(\\\\\\\\)"
                  lastPos = texte1.search(liste_noms, index = lastPos, stopindex = tkinter.END, regexp = 1, count = nmbChar )
                  if lastPos == "" :
                        break
                  texte1.tag_add( 'environnement', lastPos, "%s + %d chars" % ( lastPos, nmbChar.get() )  )
                  lastPos = "%s + 1 chars" % lastPos
            texte1.tag_configure( 'environnement', foreground = 'blue',font=("courier",10))
            lastPos = "1.0"
            while 1 :
                  liste_noms="[\{\(\[\|_\^@\)\]\}]"
                  lastPos = texte1.search(liste_noms, index = lastPos, stopindex = tkinter.END, regexp = 1, count = nmbChar )
                  if lastPos == "" :
                        break
                  texte1.tag_add( 'delimitateur', lastPos, "%s + %d chars" % ( lastPos, nmbChar.get() )  )
                  lastPos = "%s + 1 chars" % lastPos
            texte1.tag_configure( 'delimitateur', foreground = 'dark orange',font=("Courier",10,"bold"))
            lastPos = "1.0"
            while 1 :
                  liste_noms=(r"(\\\()((.|\n)*?)(\\\))")
                  lastPos=texte1.search(liste_noms, index = lastPos, stopindex = tkinter.END, regexp = 1, count = nmbChar )
                  if lastPos == "" :
                        break
                  texte1.tag_add( 'equation', lastPos, "%s + %d chars" % ( lastPos, nmbChar.get() )  )
                  lastPos = "%s + 1 chars" % lastPos
            lastPos = "1.0"
            while 1 :
                  liste_noms=(r"(\\\[)((.|\n)*?)(\\\])")
                  lastPos=texte1.search(liste_noms, index = lastPos, stopindex = tkinter.END, regexp = 1, count = nmbChar )
                  if lastPos == "" :
                        break
                  texte1.tag_add( 'equation', lastPos, "%s + %d chars" % ( lastPos, nmbChar.get() )  )
                  lastPos = "%s + 1 chars" % lastPos
            lastPos = "1.0"
            while 1 :
                  liste_noms=(r"(\\<)((.|\n)*?)(\\>)")
                  lastPos=texte1.search(liste_noms, index = lastPos, stopindex = tkinter.END, regexp = 1, count = nmbChar )
                  if lastPos == "" :
                        break
                  texte1.tag_add( 'equation', lastPos, "%s + %d chars" % ( lastPos, nmbChar.get() )  )
                  lastPos = "%s + 1 chars" % lastPos
            texte1.tag_configure( 'equation', foreground = 'purple',font=("Courier",10))        
            lastPos = "1.0"
            while 1 :
                  liste_noms="(\\\\\()|(\\\\\))|(\\\\\[)|(\\\\\])|(\\$)|([0-9<>])"
                  lastPos = texte1.search(liste_noms, index = lastPos, stopindex = tkinter.END, regexp = 1, count = nmbChar )
                  if lastPos == "" :
                        break
                  texte1.tag_add( 'chiffre', lastPos, "%s + %d chars" % ( lastPos, nmbChar.get() )  )
                  lastPos = "%s + 1 chars" % lastPos
            texte1.tag_configure( 'chiffre', foreground = 'dark violet',font=("Courier",10,"bold"))        
            lastPos = "1.0"
            while 1 :
                  liste_noms="([^\\\\]|\\n)(%)([^\\n]*?)(\\n)"
                  lastPos = texte1.search(liste_noms, index = lastPos, stopindex = tkinter.END, regexp = 1, count = nmbChar )
                  if lastPos == "" :
                        break
                  texte1.tag_add( 'commentaire', lastPos, "%s + %d chars" % ( lastPos, nmbChar.get() )  )
                  lastPos = "%s + 1 chars" % lastPos
            texte1.tag_configure( 'commentaire', foreground = 'dark gray',font=("Courier",10,"bold"))
    Moins facile à comprendre pour moi:
    Intuitivement, la mise en forme n'est importante que pour ce que l'utilisateur "voit" i.e. la partie affichée du texte qui n'en est qu'un sous ensemble.
    Il serait peut être "utile" de penser à séparer le bout de texte qu'on voit du texte sauvé dans le fichier.
    Je pensais avoir séparé le contenu du widget Text du contenu du fichier. Mais c'est peut-être là la non performance de mon programme de couleur de syntaxe mais j'ai trouvé que ce moyen pour réactualiser la couleur de syntaxe dans le widget Text.

    Enfin:
    Dans votre cas t.after ( 5000, syntaxe_couleur ) avec un repost de la même chose en sortie de syntaxe_couleur devrait suffire.
    Je ne connaissais pas l'action objet.after (je suis débutant en info et en python). Je vais essayer de l'appliquer. Cependant, s'il y a une solution plus efficace pour la coloration de syntaxe et qu'il n'y a pas de risques de conflit, je suis bien sûr plus intéressé par une coloration événementielle.

    Merci pour les réponses.
    Gabriel

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 754
    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 754
    Par défaut
    Salut,

    Je pensais avoir séparé le contenu du widget Text du contenu du fichier. Mais c'est peut-être là la non performance de mon programme de couleur de syntaxe mais j'ai trouvé que ce moyen pour réactualiser la couleur de syntaxe dans le widget Text.
    Pardon, je vous égare probablement car je n'avais pas "capté" que vous ne coloriez que la syntaxe.

    Cependant, s'il y a une solution plus efficace pour la coloration de syntaxe et qu'il n'y a pas de risques de conflit, je suis bien sûr plus intéressé par une coloration événementielle.
    Ne sachant trop jusqu'où vous voulez aller, je n'ai ni la prétention ni le temps de réfléchir à ce qui pourrait être efficace. Néanmoins, il y a sans doute de bonne idées à piocher ici ou là et peut être dans le code d'IDLE.
    IDLE est l'environnement de développement "intégré" à Python.
    Il est écrit en Python et construit avec tkinter.
    IDLE fait de la coloration de syntaxe pour les scripts python "édités" dans un widget text.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonjour,

    1) Oubliez les threads. Tkinter a déjà un gestionnaire d’événement, autant l'utiliser. Exemple sur votre 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
    import tkinter
     
    def syntaxe_couleur(event=None):
        contents = t.get(1.0, tkinter.END)
        coordonnees = t.index(tkinter.INSERT) 
        t.delete("1.0", tkinter.END)
        t.insert("1.0", contents)
        t.mark_set(tkinter.INSERT, coordonnees)
        t.see(coordonnees)      
     
        nmbChar = tkinter.IntVar()
        lastPos = "1.0"
        while 1 :
                liste_noms="[0-9]"
                lastPos = t.search(liste_noms, index=lastPos, stopindex=tkinter.END,
                                   regexp=1, count=nmbChar )
                if lastPos == "" :
                    break
                t.tag_add('commandes', lastPos, "%s + %d chars" % (lastPos,
                                                                   nmbChar.get()))
                lastPos = "%s + 1 chars" % lastPos
        t.tag_configure('commandes', foreground='red', font=("courier", 10))
        t.after(5, syntaxe_couleur)
     
    root = tkinter.Tk()
    t = tkinter.Text(root)
    t.focus_set()
    t.pack()
    t.after(5, syntaxe_couleur)
    root.mainloop()
    Attention:
    widget.after(temps_en_ms, calllback)
    Si votre callback est long ne bouclez pas trop vite.

    2) Oubliez time.spleep(x) qui est bloquant pour le code.

    Ensuite:
    Je pense que mon programme de coloration synthétique n'est pas performant (dans le code ci-dessus, il n'y avait qu'un bout). J'avais commencé par faire un root.bind('<KeyPress>',syntaxe_couleur) mais j'ai remarqué à l'usage, que le traitement pouvait s'avérer long (presque 1s) lorsque le fichier devient lourd ce qui est gênant lorsque l'on tape son texte...
    La deuxième raison, c'est que j'ai déjà <<réservé>> le '<keypress>' pour une complémentation automatique et je crains (peut-être à tort) qu'il y ait un <<conflit>> d'actions déclenchées par la même touche.
    Pour ce qui est de la performance en terme de vitesse les regex ne sont pas réputés pour cela. D'autant plus si vous les cumulez.
    Pourquoi ne pas 'planifier' tout cela ? Histoire de laisser souffler les autres.
    Exemple:
    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
    import tkinter
     
     
    def syntaxe_chiffre():
        liste_noms="[0-9]"
        lastPos = "1.0"
        while 1:
                lastPos = t.search(liste_noms, index=lastPos, stopindex=tkinter.END,
                                   regexp=1, count=nmbChar )
                if not lastPos:
                    break
                t.tag_add('chiffre', lastPos, "%s + %d chars" % (lastPos,
                                                                   nmbChar.get()))
                lastPos = "%s + 1 chars" % lastPos
        t.tag_configure('chiffre', foreground='red', font=("courier", 10))
        t.after(50, syntaxe_lettres) # <<<<< On laisse 'souffler'
     
    def syntaxe_lettres():
        liste_noms = "[a-zA-Z]"
        lastPos = "1.0"
        while 1 :
            lastPos = t.search(liste_noms, index=lastPos, stopindex=tkinter.END,
                               regexp=1, count=nmbChar)
            if not lastPos:
                break
            t.tag_add( 'lettre', lastPos, "%s + %d chars" % (lastPos,
                                                                nmbChar.get()))
            lastPos = "%s + 1 chars" % lastPos
        t.tag_configure( 'lettre', foreground='blue', font=("courier",10))
        # after suivant ici
    # Etc...
     
    def completion(event):
        # Code de completion
        t.after(50, syntaxe_chiffre) # Ou plutot directement syntaxe_chiffre()
     
    root = tkinter.Tk()
    t = tkinter.Text(root)
    t.focus_set()
    t.pack()
    nmbChar = tkinter.IntVar()
    t.bind('<KeyPress>', completion)
    root.mainloop()
    @+

  6. #6
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Un exemple en continu:

    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
    import tkinter
     
     
    def syntaxe_chiffre():
        if not syntaxe_flag.get():
            # S'il n'y a pas de verif en cours je prend la main
            syntaxe_flag.set(1)
        else:
            # Sinon j'attend
            t.after(500, syntaxe_chiffre)
            # Et on n'execute pas le reste
            return
        liste_noms="[0-9]"
        lastPos = "1.0"
        while 1:
                lastPos = t.search(liste_noms, index=lastPos, stopindex=tkinter.END,
                                   regexp=1, count=nmbChar )
                if not lastPos:
                    break
                t.tag_add('chiffre', lastPos, "%s + %d chars" % (lastPos,
                                                                   nmbChar.get()))
                lastPos = "%s + 1 chars" % lastPos
        t.tag_configure('chiffre', foreground='red', font=("courier", 10))
        # On rend la main
        syntaxe_flag.set(0)
        # Jusqu'au prochain tour
        t.after(500, syntaxe_chiffre)
     
    def syntaxe_lettres():
        if not syntaxe_flag.get(): # Verifier directement (not) pour prendre directement la main ?
            # S'il n'y a pas de verif en cours je prend la main
            syntaxe_flag.set(1)
        else:
            # Sinon j'attend
            t.after(500, lettres)
            # Et on n'execute pas le reste
            return
        liste_noms = "[a-zA-Z]"
        lastPos = "1.0"
        while 1 :
            lastPos = t.search(liste_noms, index=lastPos, stopindex=tkinter.END,
                               regexp=1, count=nmbChar)
            if not lastPos:
                break
            t.tag_add( 'lettre', lastPos, "%s + %d chars" % (lastPos,
                                                                nmbChar.get()))
            lastPos = "%s + 1 chars" % lastPos
        t.tag_configure( 'lettre', foreground='blue', font=("courier",10))
        # On rend la main
        syntaxe_flag.set(0)
        # Jusqu'au prochain tour
        t.after(500, syntaxe_lettres)
     
     
    root = tkinter.Tk()
    t = tkinter.Text(root)
    t.focus_set()
    t.pack()
    nmbChar = tkinter.IntVar()
    syntaxe_flag = tkinter.BooleanVar(0)
    t.after(50, syntaxe_chiffre)
    t.after(100, syntaxe_lettres)
    root.mainloop()
    Mais je n'aime pas trop car on a pas 'la main' sur les events. Passer par une visit_method / poller_routine ? Sans doute mais pas ce matin

    @+

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

Discussions similaires

  1. [XL-2007] Répéter une action plusieurs fois
    Par Guiggs dans le forum Macros et VBA Excel
    Réponses: 11
    Dernier message: 08/07/2013, 18h25
  2. Exécuter une action en boucle pendant un temps donné
    Par greg_78 dans le forum Général Python
    Réponses: 10
    Dernier message: 07/10/2010, 07h09
  3. Répéter une action monadique
    Par limestrael dans le forum Haskell
    Réponses: 6
    Dernier message: 17/12/2009, 22h34
  4. répéter une action
    Par Lubovic dans le forum VB.NET
    Réponses: 10
    Dernier message: 27/01/2009, 19h26
  5. Réponses: 4
    Dernier message: 15/06/2006, 10h05

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