Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 13 sur 13
  1. #1
    Invité de passage
    Femme Profil pro
    Étudiant
    Inscrit en
    juin 2012
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Islande

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Arts - Culture

    Informations forums :
    Inscription : juin 2012
    Messages : 5
    Points : 2
    Points
    2

    Par défaut execution periodique avec GUI

    Bonjour,
    je recherche un moyen simple d´executer periodiquement (toutes les x min.) une commande. L´execution periodique doit commencer quand l´utilisateur appuie sur un bouton "commencer" et s´arreter lorsqu´il appuie sur un bouton "terminer".

    J´ai bien reussi avec Tkinter de Python a faire les boutons, mais je ne sais pas comment faire l´execution periodique qui s´arreterait quand on appuie sur un bouton.
    Quelqu´un pourrait-il me dire comment faire? Si possible sans trop consommer de ressource.

  2. #2
    Expert Confirmé Avatar de PauseKawa
    Homme Profil pro Patrice BLANGARIN
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    juin 2006
    Messages
    2 720
    Détails du profil
    Informations personnelles :
    Nom : Homme Patrice BLANGARIN
    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 720
    Points : 3 953
    Points
    3 953

    Par défaut

    Bonjour,

    Pas compris: Si c'est périodique pas besoin de bouton "commencer" /"terminer". Cela se passe via un daemon/thread etc... Et pas besoin de GUI.
    Pouvez vous préciser ce que vous voulez faire ?
    Pour ce qui est de Tkinter avez vous vus que le Widget Button a une option command ? C'est pour spécifier une fonction a exécuter.

    @+
    Merci d'utiliser le forum pour les questions techniques.

  3. #3
    Expert Confirmé Avatar de PauseKawa
    Homme Profil pro Patrice BLANGARIN
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    juin 2006
    Messages
    2 720
    Détails du profil
    Informations personnelles :
    Nom : Homme Patrice BLANGARIN
    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 720
    Points : 3 953
    Points
    3 953

    Par défaut

    Voila pour la partie GUI
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    import sys
     
    if sys.version_info[0] > 2:
        import tkinter as tk
    else:
        import Tkinter as tk
     
    def hideme():
        root.withdraw()
        root.after(2000, root.deiconify) # 2000 est en ms
     
    root = tk.Tk()
    tk.Button(root, text="Cacher", command=hideme).pack(padx=5, pady=5)
    tk.Button(root, text="Quitter", command=root.destroy).pack(padx=5, pady=5)
    root.mainloop()
    Pour le reste dans l'attente de vous lire.

    @+
    Merci d'utiliser le forum pour les questions techniques.

  4. #4
    Expert Confirmé

    Homme Profil pro
    Inscrit en
    octobre 2008
    Messages
    1 910
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : octobre 2008
    Messages : 1 910
    Points : 2 936
    Points
    2 936

    Par défaut

    Salut,

    Moi, je comprends plutôt que le bouton sert simplement à mettre en marche le timer et ensuite à le stopper.

    Si c'est bien cela, il suffit de montrer le code du timer, il doit bien y avoir un moyen de l'arrêter.
    Vincent
    Oqapy . Qarte . PaQager

  5. #5
    Invité de passage
    Femme Profil pro
    Étudiant
    Inscrit en
    juin 2012
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Islande

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Arts - Culture

    Informations forums :
    Inscription : juin 2012
    Messages : 5
    Points : 2
    Points
    2

    Par défaut

    Ce que j´ entends par periodique c´est une repetition a intervalle regulier d´une commande jusqu´a ce que l´utilisateur dise: stop. L´information stop peut etre donne par GUI, ce n´est effectivement pas obligatoire, mais plus pratique.

    Je pourrais lancer une boucle infinie genre:

    while true
    ma commande
    pause x min

    et "killer" le processus quand je veux l´arreter, mais ce n´est pas tres elegant comme methode!

    En fait j´ai ecrit un script python qui actualise une base de donnee. J´aimerai pouvoir lancer regulierement (toutes les x min.) ce script quand j´ai besoin d´avoir cette base de donnee toujours actualisee. Quand je n´en ai plus besoin, j´aimerais pouvoir arreter l´actualisation de ma base de donnee.

  6. #6
    Expert Confirmé

    Homme Profil pro
    Inscrit en
    octobre 2008
    Messages
    1 910
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : octobre 2008
    Messages : 1 910
    Points : 2 936
    Points
    2 936

    Par défaut

    C'est bien ce que j'avais copris, mais ton 'timer' tu l'as écrit comment ?

    Un thread ? threading.Timer ?

    Une boucle while, ça m'étonnerait.

    Bref, on veut du code.
    Vincent
    Oqapy . Qarte . PaQager

  7. #7
    Modérateur

    Homme Profil pro
    Architecte technique
    Inscrit en
    juin 2008
    Messages
    5 523
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Industrie

    Informations forums :
    Inscription : juin 2008
    Messages : 5 523
    Points : 8 338
    Points
    8 338

    Par défaut

    Salut

    Avec Tkinter, vous avez la méthode .after(delay, callback) qui permet d'appeler la fonction "callback" après "delay" millisecondes.

    La discussion récente montre comment utiliser la chose pour "répéter" l'opération "tant que".

    La méthode .after retourne un identifiant qui pourra être passé en paramètre à la méthode .cancel pour arrêter le monstre.

    Ces méthodes .after, .cancel sont disponibles pour tous les widgets Tk.
    Vous pouvez aussi lire la discussion qui traite de ce sujet.

    Ces indications devrait vous permettre d'écrire un premier code et de râler sur les aspects que vous ne comprenez pas.

    - W
    Architectures Post-Modernes

  8. #8
    Invité de passage
    Femme Profil pro
    Étudiant
    Inscrit en
    juin 2012
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Islande

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Arts - Culture

    Informations forums :
    Inscription : juin 2012
    Messages : 5
    Points : 2
    Points
    2

    Par défaut

    La methode .after(delay, callback) marche nickel! Par contre je n´arrive pas a l´arreter avec le .cancel. Comment utilise-t-on le .cancel? Auriez-vous un exemple?
    Voici un extrait de mon code:

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
     
    class App:
    	def __init__(self,parent):
    #...
    	def update_loop(self):
    		#ici ma commade "lancer actualisation". Pr l instant juste un print:
                    print periode
    	        boucle_identifiant=root.after(1000, self.update_loop)
     
     
    	def stop_loop(self):
    		root.cancel(boucle_identifiant)
     
    root = Tk()
    app = App(root)
    root.mainloop()

  9. #9
    Modérateur

    Homme Profil pro
    Architecte technique
    Inscrit en
    juin 2008
    Messages
    5 523
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Industrie

    Informations forums :
    Inscription : juin 2008
    Messages : 5 523
    Points : 8 338
    Points
    8 338

    Par défaut

    Désolé, j'ai m...
    Il faut utiliser .after_cancel et non .cancel (que je ne sais même pas ce que c'est):

    Un exemple posté, il y a longtemps:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    counter_id = None
    def decompte(count=10):
        global counter_id
        lab['text'] = count
        if count > 0 :
            counter_id = fen1.after(1000, decompte, count-1)
     
    def stop():
        if counter_id:
            fen1.after_cancel(counter_id)
            lab['text'] = "stop!"
    - W
    Architectures Post-Modernes

  10. #10
    Invité de passage
    Femme Profil pro
    Étudiant
    Inscrit en
    juin 2012
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Islande

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Arts - Culture

    Informations forums :
    Inscription : juin 2012
    Messages : 5
    Points : 2
    Points
    2

    Par défaut

    Merci ca marche nickel!

    Mon code si ca interesse quelqu´un:

    Code :
    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
    import glob, os
    import sys
    import time, threading
    from Tkinter import *
    from tkFileDialog import askopenfilename
     
     
    class App:
    	def __init__(self,parent):
     
    		f = Frame(parent)
    		f.pack(padx=15,pady=15)
     
       		self.entry = Entry(f,text="enter your choice")
    		self.entry.pack(side= TOP,padx=10,pady=12)
     
    		self.exit = Button(f, text="exit", command=f.quit)
    		self.exit.pack(side=BOTTOM,padx=10,pady=10)
     
    		self.button = Button(f, text="print bonjour",command=self.effacer_intraday)
    		self.button.pack(side=BOTTOM,padx=10,pady=10)
     
    		self.button = Button(f, text="print once",command=self.update_once)
    		self.button.pack(side=BOTTOM,padx=10,pady=10)
     
    		self.button = Button(f, text="Stop",command=self.stop_loop)
    		self.button.pack(side=BOTTOM,padx=10,pady=10)
     
    		self.button = Button(f, text="print each second",command=self.update_loop)
    		self.button.pack(side=BOTTOM,padx=10,pady=10)
     
     
    	def effacer_intraday(self):
    		print "bonjour"
     
    	def update_loop(self):
    		global counter_id
    		periode = self.entry.get()
    		print periode
    	        counter_id =root.after(1000, self.update_loop)
     
    	def update_once(self):
    		periode = self.entry.get()
    		print periode
     
    	def stop_loop(self):
    	    if counter_id:
    	        root.after_cancel(counter_id)
     
     
    root = Tk()
    root.title('Tkwidgets application')
    Label (text="Enter text to print:").pack(side=TOP,padx=0,pady=0)
    app = App(root)
    root.mainloop()

  11. #11
    Expert Confirmé Avatar de PauseKawa
    Homme Profil pro Patrice BLANGARIN
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    juin 2006
    Messages
    2 720
    Détails du profil
    Informations personnelles :
    Nom : Homme Patrice BLANGARIN
    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 720
    Points : 3 953
    Points
    3 953

    Par défaut

    Bonjour,

    Deux ou trois petites choses qui me sont venues à l'esprit à la lecture du code:

    Ne mélanger pas tabulations et espaces.

    Pas besoin de global puisque vous avez self.

    Utilisez parent.destroy et non f.quit.

    Le fait d'utiliser le même nom pour tout vos Widgets Button fait vous écrasez la référence à chaque fois. Mais au fait: Pourquoi la garder puisque seul command nous intéresses.

    padx=0,pady=0 ne sert à rien. De même ici les side= puisque .pack() le places de haut en bas. Mais bon, cela ne gène en rien.

    L’intérêt du Label hors de la Frame ? Et l’intérêt de la Frame en fait puisque .pack() positionne les Widgets de haut en bas ?

    root.after(1000, self.update_loop) ? self.parent.after(1000, self.update_loop) En fait.

    Code :
    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
    from Tkinter import *
     
     
    class App:
        def __init__(self, parent):
            self.parent = parent
            Label(self.parent, text="Enter text to print:").pack(padx=10, pady=10)
            self.entry = Entry(self.parent, text="enter your choice")
            self.entry.pack(padx=10, pady=10)
     
            Button(self.parent, text="exit", command=self.parent.destroy).pack(padx=10, pady=10)
     
            Button(self.parent, text="print bonjour", command=self.effacer_intraday).pack(padx=10, pady=10)
     
            Button(self.parent, text="print once", command=self.update_once).pack(padx=10, pady=10)
     
            Button(self.parent, text="Stop", command=self.stop_loop).pack(padx=10, pady=10)
            Button(self.parent, text="print each second", command=self.update_loop).pack(padx=10, pady=10)
     
        def effacer_intraday(self):
            print "bonjour"
     
        def update_loop(self):
            periode = self.entry.get()
            print periode
            self.counter_id = self.parent.after(1000, self.update_loop)
     
        def update_once(self):
            periode = self.entry.get()
            print periode
     
        def stop_loop(self):
            if self.counter_id:
                root.after_cancel(self.counter_id)
     
     
    root = Tk()
    root.title('Tkwidgets application')
    app = App(root)
    root.mainloop()
    Je vois un import threading donc je pense que c'est utile pour votre code complet: Attention avec Tkinter qui n'est pas threadsave.

    Astuce: Lorsque vous utilisez les mêmes options de géométrie pour un groupe de Widget vous pouvez utiliser un dico.

    L’intérêt de la classe ici ? A la limite si cela dérive de Tk.

    if self.counter_id est source à erreur (AttributeError) si vous cliquez sur stop avant. Soit vous utilisez hasattr, soit (le plus simple) vous donnez une valeur à self.counter_id.
    Code :
    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
     
    from Tkinter import *
     
     
    class App(Tk):
        def __init__(self):
            Tk.__init__(self)
            self.title('Tkwidgets application')
            geometry = {'padx': 10, 'pady': 10}
            self.counter_id = None
     
            Label(self, text="Enter text to print:").pack(geometry)
            self.entry = Entry(self, text="enter your choice")
            self.entry.pack(geometry)
     
            Button(self, text="exit", command=self.destroy).pack(geometry)
     
            Button(self, text="print bonjour", command=self.effacer_intraday).pack(geometry)
     
            Button(self, text="print once", command=self.update_once).pack(geometry)
     
            Button(self, text="Stop", command=self.stop_loop).pack(geometry)
            Button(self, text="print each second", command=self.update_loop).pack(geometry)
            self.mainloop()
     
        def effacer_intraday(self):
            print("bonjour")
     
        def update_loop(self):
            print(self.entry.get())
            self.counter_id = self.after(1000, self.update_loop)
     
        def update_once(self):
            print(self.entry.get())
     
        def stop_loop(self):
            if self.counter_id:
                self.after_cancel(self.counter_id)
     
     
    if __name__ == "__main__":
        App()
    Petit modif pour rendre l'exemple compatible Python 2/3

    Code :
    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
    import sys
    if sys.version_info[0] > 2:
        import tkinter as tk
    else:
        import Tkinter as tk 
     
     
    class App(tk.Tk):
        def __init__(self):
            tk.Tk.__init__(self)
            self.title('Tkwidgets application')
            geometry = {'padx': 10, 'pady': 10}
            self.counter_id = None
     
            tk.Label(self, text="Enter text to print:").pack(geometry)
            self.entry = tk.Entry(self, text="enter your choice")
            self.entry.pack(geometry)
     
            tk.Button(self, text="exit", command=self.destroy).pack(geometry)
     
            tk.Button(self, text="print bonjour", command=self.effacer_intraday).pack(geometry)
     
            tk.Button(self, text="print once", command=self.update_once).pack(geometry)
     
            tk.Button(self, text="Stop", command=self.stop_loop).pack(geometry)
            tk.Button(self, text="print each second", command=self.update_loop).pack(geometry)
            self.mainloop()
     
        def effacer_intraday(self):
            print("bonjour")
     
        def update_loop(self):
            print(self.entry.get())
            self.counter_id = self.after(1000, self.update_loop)
     
        def update_once(self):
            print(self.entry.get())
     
        def stop_loop(self):
            if self.counter_id:
                self.after_cancel(self.counter_id)
     
     
    if __name__ == "__main__":
        App()
    Une autre astuce au passage pour les Widgets identiques

    Code :
    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
    import sys
    if sys.version_info[0] > 2:
        import tkinter as tk
    else:
        import Tkinter as tk 
     
     
    class App(tk.Tk):
        def __init__(self):
            tk.Tk.__init__(self)
            self.title('Tkwidgets application')
            geometry = {'padx': 10, 'pady': 10}
            self.counter_id = None
     
            tk.Label(self, text="Enter text to print:").pack(geometry)
            self.entry = tk.Entry(self, text="enter your choice")
            self.entry.pack(geometry)
     
            buttons = {"exit": self.destroy, "print bonjour": self.effacer_intraday,
                       "print once": self.update_once, "Stop": self.stop_loop,
                       "print each second": self.update_loop}
     
            for cmd in buttons:
                tk.Button(self, text=cmd, command=buttons[cmd]).pack(geometry)
     
            self.mainloop()
     
        def effacer_intraday(self):
            print("bonjour")
     
        def update_loop(self):
            print(self.entry.get())
            self.counter_id = self.after(1000, self.update_loop)
     
        def update_once(self):
            print(self.entry.get())
     
        def stop_loop(self):
            if self.counter_id:
                self.after_cancel(self.counter_id)
     
     
    if __name__ == "__main__":
        App()
    Mais en fait ici pas besoin d'une classe

    Code :
    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
    import sys
    if sys.version_info[0] > 2:
        import tkinter as tk
    else:
        import Tkinter as tk 
     
     
    def effacer_intraday():
        print("bonjour")
     
    def update_loop():
        print(entry.get())
        root.counter_id = root.after(1000, update_loop)
     
    def update_once():
        print(entry.get())
     
    def stop_loop():
        if root.counter_id:
            root.after_cancel(root.counter_id)
     
     
    root = tk.Tk()
    root.title('Tkwidgets application')
    geometry = {'padx': 10, 'pady': 10}
    root.counter_id = None
     
    tk.Label(root, text="Enter text to print:").pack(geometry)
    entry = tk.Entry(root, text="enter your choice")
    entry.pack(geometry)
     
    buttons = {"exit": root.destroy, "print bonjour": effacer_intraday,
               "print once": update_once, "Stop": stop_loop,
               "print each second": update_loop}
     
    for cmd in buttons:
        tk.Button(root, text=cmd, command=buttons[cmd]).pack(geometry)
     
    root.mainloop()
    @+ et bon code

    Edit: Bonus géométrique
    geometry = {'padx': 10, 'pady': 10, 'fill': tk.BOTH}

    Edit: Erreur de tabulation.
    Merci d'utiliser le forum pour les questions techniques.

  12. #12
    Invité de passage
    Femme Profil pro
    Étudiant
    Inscrit en
    juin 2012
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Islande

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Arts - Culture

    Informations forums :
    Inscription : juin 2012
    Messages : 5
    Points : 2
    Points
    2

    Par défaut

    En fait mon code c´ est de la recupe de codes que j'ai trouve sur internet. D'ou toutes les incoherences. Je debute en python, c'est l'un de mes premiers codes.
    En tous cas, merci a tous pour votre aide!

    Juste une petite derniere question. L'execution de la boucle periodique n'est en fait pas exactement periodique.

    La periode d'execution de la fonction update_loop:
    Code :
    1
    2
    3
    def update_loop():
        print(entry.get())
        root.counter_id = root.after(1000, update_loop)
    est en faite de 1 seconde + le temps d'execution de:
    Bon dans ce cas, l'execution de print est quasi instantannee, donc ca n'a pas d'importance. Mais j'utilise ce code pour lancer un autre python (actualiser une base de donnee), dont le temps d'execution est non negligeable et irregulier. La meilleure solution que j'ai trouve pour que la periode d'execution de la fonction update_loop soit independante de la duree de l'application que je lance (ici print(entry.get()) ), c'est de mettre le root.after avant le print:
    Code :
    1
    2
    3
    def update_loop():
        root.counter_id = root.after(1000, update_loop)
        print(entry.get())
    Je voulais juste avoir votre avis sur cette astuce. Est-ce correcte? Bon chez moi ca a l'air demarche.

  13. #13
    Expert Confirmé Avatar de PauseKawa
    Homme Profil pro Patrice BLANGARIN
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    juin 2006
    Messages
    2 720
    Détails du profil
    Informations personnelles :
    Nom : Homme Patrice BLANGARIN
    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 720
    Points : 3 953
    Points
    3 953

    Par défaut

    C'est bien cela.
    Je rajouterais que si vous modifiez quelque chose il n'est sans doute pas bon de lancer le même traitement deux fois en même temps, dans le cas ou le premier n'est pas fini. Comprendre que votre traitement doit 'signaler' qu'il a fini avant d'en faire un autre.
    Code :
    1
    2
    3
    4
    5
    def update_loop():
        root.counter_id = root.after(1000, update_loop)
        if in_progress:
            return
        #ici le code qui à la fin fait un in_progress = False. Utilisez self.in_progress ou global au choix.
    Merci d'utiliser le forum pour les questions techniques.

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

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •