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 :

Créer un event pout Tkinter


Sujet :

Tkinter Python

  1. #1
    Membre expérimenté
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    946
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 946
    Points : 1 351
    Points
    1 351
    Par défaut Créer un event pout Tkinter
    Salut,

    Je dois émettre recevoir des messages d'une uart sous Tkinter et je voudrais rester en événementiel. Je dois donc créer un thread qui reçoit les messages et qui envoie des évènements. Pour le thread, ça va, je suis parti de la FAQ python, mais pour les events, je ne vois pas trop. Il y a bien les virtual events dans Tkinter, mais si j'ai bien compris, l’émetteur de l'event ne peut être qu'une combinaison de touches. Donc si quelqu'un a une piste pour créer un event, je suis preneur.

    Dans l'exemple ci-dessous, c'est le fonctionnement que je ne veux pas, à savoir que c'est le thread eventMaker qui traite le message parce que je n'ai pas pu faire fonctionner les lignes commentées.

    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
    import threading
    import sys
    import time
    import Tkinter
    import random
     
    class EVENT():
        def __init__(self, text='???'):
            self.message = text
     
        def get(self):
            return self.message
     
    def eventMaker(text, running, win):
        while running.get():
            if random.randint(0, 1000) == 0:
                sys.stdout.write(text)
                #~ win.event_add("<<message>>", EVENT(text))
                eventShow(EVENT(text))
            time.sleep(0.001)
     
    def eventShow(message):
        if message.get() == 'a':
            a_counter.set(a_counter.get() + 1)
        elif message.get() == 'b':
            b_counter.set(b_counter.get() + 1)
     
    win = Tkinter.Tk()
    #~ win.bind("<<can_msg>>", eventShow)
    running = Tkinter.IntVar(value=1)
     
    a_counter = Tkinter.IntVar(value=0)
    b_counter = Tkinter.IntVar(value=0)
     
    Tkinter.Label(win, textvariable=a_counter, width=20).grid()
    Tkinter.Label(win, textvariable=b_counter, width=20).grid()
     
    a = threading.Thread(None, eventMaker, None, ('a', running, win))
    b = threading.Thread(None, eventMaker, None, ('b', running, win))
    a.start()
    b.start()
     
    win.mainloop()
    running.set(0)
    sys.stdout.write('\nend of program\n')

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 241
    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 241
    Points : 36 698
    Points
    36 698
    Par défaut
    Salut,
    Les virtual events doivent être associés à une sequence de caractères tapés au clavier ou action sur le mouse.
    Dans votre cas, les threads postent des mises à jour de l'affichage du GUI.

    Mais vous utilisez deux stratégies différentes: IntVar qui est un observable et le déclenchement d'une opération dans le contexte du Gui via le post d'une méthode.

    Via observable IntVar:
    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
    import threading
    import time
    import Tkinter as tk
    from Tkconstants import *
     
    def event_maker(counter, stop_event):
        value = counter.get()
        while not stop_event.is_set():
            value += 1
            counter.set(value)
            print ('value = %d' % value)
            time.sleep(0.1)
     
    root = tk.Tk()
    a_counter = tk.IntVar(value=0)
    tk.Label(root, textvariable=a_counter, width=20).pack(side=TOP, fill=X)
    b_counter = tk.IntVar(value=0)
    tk.Label(root, textvariable=b_counter, width=20).pack(side=TOP, fill=X)
     
    stop_event = threading.Event()
    threading.Thread(target=event_maker, args=(a_counter, stop_event)).start()
    threading.Thread(target=event_maker, args=(b_counter, stop_event)).start()
    root.mainloop()
    stop_event.set()
    Post d'une méthode via root.after_idle.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    def event_maker(counter, stop_event):
        value = counter.get()
        while not stop_event.is_set():
            value += 1
            root.after_idle(counter.set, value)
            print ('value = %d' % value)
            time.sleep(0.1)
    Cordialement,
    - W
    PS: tkinter et tk ne sont pas ré-entrants => on ne peut pas "changer" l'état du GUI depuis un autre thread que la thread qui l'a lancée - la principale -. Suivant les options de compilations, ils peuvent être threadsafe: les accès aux différentes structures de données sont protégées par des verrous "globaux". Si on ne veut pas trop se poser de question, il est d'usage d'intercaler une Queue de messages entre threads et tkinter. Les messages sont les méthodes et paramètres qui devront être exécutés dans le contexte du GUI. Et on réalise un poller déclenché périodiquement via la mainloop qui vide la Queue pour poster les message dans l'event queue via .after.
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre expérimenté
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    946
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 946
    Points : 1 351
    Points
    1 351
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Salut,
    Les virtual events doivent être associés à une sequence de caractères tapés au clavier ou action sur le mouse.
    Dans votre cas, les threads postent des mises à jour de l'affichage du GUI.
    Bon, merci, ça confirme que les virtuals events ne peuvent être déclenchés que par appui d'une touche ou la souris.

    Citation Envoyé par wiztricks Voir le message
    Si on ne veut pas trop se poser de question, il est d'usage d'intercaler une Queue de messages entre threads et tkinter. Les messages sont les méthodes et paramètres qui devront être exécutés dans le contexte du GUI. Et on réalise un poller déclenché périodiquement via la mainloop qui vide la Queue pour poster les message dans l'event queue via .after.
    Je pense que je vais faire comme ça, donc un polling via after. merci beaucoup.

    A+

    Pfeuh

  4. #4
    Expert confirmé 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
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonsoir,

    Pour ce qui est des virtual events il est bon de préciser que la porte est grande ouverte:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import Tkinter as tk
     
    def onevent(e):
        t['text'] = 'event'
     
    root = tk.Tk()
    t = tk.Label(root)
    t.pack()
    root.event_add('<<myevent>>', "<Button-4>")
    root.bind('<<myevent>>', onevent)
    tk.Button(root, text='Quit', command=root.destroy).pack(padx=5, pady=5)
    root.after(1000, lambda: root.event_generate('<<myevent>>'))
    root.mainloop()
    Perso je suis contre l'utilisation de la classe Variable avec des threads. La valeur passe à None lors du changement et faire de l'asynchrone sur de l'asynchrone c'est limite non ?

    Pourquoi threading, time ? Et .after() ? Au moins cela reste dans le mainloop.

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

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 241
    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 241
    Points : 36 698
    Points
    36 698
    Par défaut
    Bonsoir PauseKawa,

    Dans:
    Citation Envoyé par PauseKawa Voir le message
    Perso je suis contre l'utilisation de la classe Variable avec des threads. La valeur passe à None lors du changement et faire de l'asynchrone sur de l'asynchrone c'est limite non ?
    Je ne comprends pas "La valeur passe à None lors du changement".

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

  6. #6
    Expert confirmé 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
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonsoir wiztricks,

    Lors de l'utilisation de threads il arrive que le .get() retourne None du fait de la mise à jour de la valeur sous tcl.
    Merci d'utiliser le forum pour les questions techniques.

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 241
    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 241
    Points : 36 698
    Points
    36 698
    Par défaut
    Salut,

    Lors de l'utilisation de threads il arrive que le .get() retourne None du fait de la mise à jour de la valeur sous tcl.
    Si TCL et _tkinter.c ont été compilés avec le support des threads, cela est difficile a comprendre (à la lecture des sources).

    Avec tant d'efforts faits pour supporter les threads, si çà ne marche pas çà sent le "bug" -- sauf à constater que les différents modules ont été compilés avec des options "contradictoires", "incohérentes".

    Comment savoir si Python, _tkinter et le tcl qui est dessous sont "cohérents" pour supporter les threads est une autre histoire!

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

  8. #8
    Membre expérimenté
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    946
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 946
    Points : 1 351
    Points
    1 351
    Par défaut
    Salut,

    Citation Envoyé par PauseKawa Voir le message
    Pour ce qui est des virtual events il est bon de préciser que la porte est grande ouverte:
    C'est noté, mais ça ressemble quand même à du bricolage puisque qu'il faut définir une combinaison de touches pour définir l'évènement, même si cette combinaison n'est pas utilisée. Et si elle est utilisable, quelqu'un va l'utiliser, c'est la loi de Murphy. De plus je n'ai pas réussi à accrocher un paramètre à l'event. Voulant faire passer un message canOpen (donc une instance d'un objet complexe, pas une chaine de caractères), j'aurais bien voulu qu'il soit accroché à l'évènement, je n'ai pas réussi à le faire.

    Citation Envoyé par PauseKawa Voir le message
    Pourquoi threading, time ?
    parce que même si le thread ne prend pas tout le temps CPU, il en prend quand même trop pour ce qu'on lui demande de faire, de plus la réception se fait entièrement sous interruptions avec des buffers de taille conséquente, c'est pourquoi j'ai encore ralenti le thread avec sleep.

    Citation Envoyé par PauseKawa Voir le message
    Et .after() ? Au moins cela reste dans le mainloop.
    C'est la solution que j'ai utilisée. Mais autour de moi j'ai eu plein de critiques quand à son utilisation, comme quoi le temps de réponse est vraiment aléatoire, etc...

    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
    import threading
    import time
    import Tkinter as tk
     
    class MESSAGE_BOX():
        def __init__(self):
            self.box = []
     
        def isBoxEmpty(self):
            if len(self.box) == 0:
                return True
            else:
                return False
     
        def post(self, message):
            self.box.append(message)
            time.sleep(0.5)
     
        def get(self):
            while self.isBoxEmpty():
                # there is no message at the moment
                time.sleep(0.001)
            message = self.box[0]
            del(self.box[0])
            return message
     
    def appQuit():
        can_reader._Thread__stop()
        win.destroy()
     
    def canReceiver(receive_box):
        # simulates reception of messages
        counter = 0
        while 1:
            time.sleep(0.5)
            counter += 1
            message = "received message %08u"%counter
            receive_box.post(message)
     
    def addToLog(log, message):
        log.insert('end', message + '\n')
        log.see('end')
     
    def canTransmitter(send_box):
        # simulates emission of messages
        canTransmitter.counter += 1 #static variable
        message = "sended message %08u"%canTransmitter.counter
        send_box.post(message)
        win.update_idletasks()
     
    def canSequencer():
        while not receive_box.isBoxEmpty():
            message = receive_box.get()
            addToLog(log, message)
        while not send_box.isBoxEmpty():
            message = send_box.get()
            addToLog(log, message)
        win.after(1, canSequencer)
     
    canTransmitter.counter = 0 # static variable
    win = tk.Tk()
    receive_box = MESSAGE_BOX()
    send_box = MESSAGE_BOX()
    log = tk.Text(win, width=40, height=25)
    log.grid()
    bt = tk.Button(win, text='send message', width=40, height=3, command=lambda box=send_box:canTransmitter(send_box))
    bt.grid()
    can_reader = threading.Thread(None, canReceiver, None, (receive_box,))
    can_reader.start()
    win.protocol('WM_DELETE_WINDOW', appQuit)
    win.after(1000, canSequencer)
    win.mainloop()

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 241
    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 241
    Points : 36 698
    Points
    36 698
    Par défaut
    Salut,

    Jamais utilisé mais .createfilehandler permet de déclarer un callback appelé par la mainloop lorsque le "descripteur" à des données à lire ou est prêt à en recevoir.
    "descripteur", l'engin sous jacent doit avoir un fileno pour que tk puisse faire un unix select dessus.
    Cela peut permettre d'intégrer des échanges externes sans avoir à créer une thread séparée,voir .
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  10. #10
    Expert confirmé 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
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonsoir,

    Citation Envoyé par pfeuh Voir le message
    C'est noté, mais ça ressemble quand même à du bricolage puisque qu'il faut définir une combinaison de touches pour définir l'évènement, même si cette combinaison n'est pas utilisée. Et si elle est utilisable, quelqu'un va l'utiliser, c'est la loi de Murphy. De plus je n'ai pas réussi à accrocher un paramètre à l'event. Voulant faire passer un message canOpen (donc une instance d'un objet complexe, pas une chaine de caractères), j'aurais bien voulu qu'il soit accroché à l'évènement, je n'ai pas réussi à le faire.
    Je n'ai pas trop compris je pense. Dans le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import Tkinter as tk
     
    def onevent(e):
        if e.num != 5:
            t['text'] = 'event'
     
    root = tk.Tk()
    t = tk.Label(root)
    t.pack()
    root.event_add('<<myevent>>', "<Button-5>")
    root.bind('<<myevent>>', onevent)
    tk.Button(root, text='Quit', command=root.destroy).pack(padx=5, pady=5)
    root.after(1000, lambda: root.event_generate('<<myevent>>'))
    root.mainloop()
    Seul l'event '<<myevent>>' déclenche le callback.
    Et pour ce qui est de 'accrocher un paramètre à l'event' lambda est très pratique pour cela.

    Citation Envoyé par pfeuh Voir le message
    C'est la solution que j'ai utilisée. Mais autour de moi j'ai eu plein de critiques quand à son utilisation, comme quoi le temps de réponse est vraiment aléatoire, etc...
    Ben... C'est pour cela que j'ai parler de n'utiliser 'que' le gestionnaire d'event tcl.

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

  11. #11
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 241
    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 241
    Points : 36 698
    Points
    36 698
    Par défaut
    Salut,

    Bon d'accord le PO veut un event, mais passer par la déclaration d'un event puis par event_generate lancé par root.after pour activer un callback alien! hu?!?

    root.after (1000, callback, args) et la liste d'arguments qu'on veut fait aussi bien non?

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

  12. #12
    Expert confirmé 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
    Points : 4 005
    Points
    4 005
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Bon d'accord le PO veut un event, mais passer par la déclaration d'un event puis par event_generate lancé par root.after pour activer un callback alien! hu?!?

    root.after (1000, callback, args) et la liste d'arguments qu'on veut fait aussi bien non?

    - W
    Le root.after n'est là que pour l'exemple donné: déclencher l'event et montrer qu'il est possible d'utiliser bind pour créer des events sous Tkinter autres que souris/clavier.
    Merci d'utiliser le forum pour les questions techniques.

  13. #13
    Membre expérimenté
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    946
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 946
    Points : 1 351
    Points
    1 351
    Par défaut
    Citation Envoyé par PauseKawa Voir le message
    Je n'ai pas trop compris je pense.
    C'est parce que je n'ai pas du être assez clair.
    Seul l'event '<<myevent>>' déclenche le callback.
    j'ai cru comprendre que '<Button-5>' pouvait déclencher l’événement aussi. Mais je viens juste de voir dans le code de onevent la ligne
    if event.num != 5:
    qui je suppose protège contre cette possibilité
    Et pour ce qui est de 'accrocher un paramètre à l'event' lambda est très pratique pour cela.
    En fait, quand on a un event clavier, on peut par exemple lire le code touche avec event.keycode. J'aurais voulu pouvoir récupérer mon message can grâce à un event.message, c'est ce que j'ai appelé 'accrocher un paramètre à l'event'. Suite à toutes ces considérations, voilà le code tel que je l'aurais aimé, dérivé du tien mais qui ne marche pas à cause de "l'accrochage d'un paramètre"

    Citation Envoyé par wiztricks Voir le message
    "descripteur", l'engin sous jacent doit avoir un fileno pour que tk puisse faire un unix select dessus.
    je n'ai pas le niveau pour pouvoir considérer mon périphérique Can comme un fichier...

    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 as tk
    import threading
    import ctypes
    import random
    import time
     
    class canMessage (ctypes.Structure):
        _fields_ = [ ("ID", ctypes.c_ulong), ("MSGTYPE", ctypes.c_ubyte), ("LEN", ctypes.c_ubyte), ("DATA", ctypes.c_ubyte * 8) ]
     
        def __str__(self):
            return "%03x %s"%(self.ID, '-'.join(["%02x"%self.DATA[x] for x in range(self.LEN)]))
     
    def buildMessage():
        """random message for demo purpose"""
        msg = canMessage()
        msg.ID = random.randint(0, 0x7ff)
        msg.MSGTYPE = 0
        msg.LEN = random.randint(0, 8)
        for idx in range(msg.LEN):
            msg.DATA[idx] = random.randint(0, 0xff)
        return msg
     
    def canReceiveThread():
        time.sleep(0.2 + random.random() * 0.1)
        msg = buildMessage()
        #~ win.event_generate('<<canMessage>>')
        win.event_generate('<<canMessage>>', message=msg)
     
    def onCanReceiveEvent(event):
        if event.num != 5:
            #~ label['text'] = 'event'
            label['text'] = str(event.message)
     
    win = tk.Tk()
    label = tk.Label(win)
    label.grid()
    win.event_add('<<myevent>>', "<Button-5>")
    win.bind('<<myevent>>', onCanReceiveEvent)
    #~ win.event_add('<<canMessage>>', "<Button-5>")
    #~ win.bind('<<canMessage>>', onCanReceiveEvent)
    can_receiver = threading.Thread(None, canReceiveThread, None)
    can_receiver.start()
    win.mainloop()

  14. #14
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 241
    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 241
    Points : 36 698
    Points
    36 698
    Par défaut
    Salut,

    Citation Envoyé par PauseKawa Voir le message
    Le root.after n'est là que pour l'exemple donné: déclencher l'event et montrer qu'il est possible d'utiliser bind pour créer des events sous Tkinter autres que souris/clavier.
    Hmm dans ce cas, faire .bind d'un string qui ressemble à un virtual event "suffit" - pas besoin de faire event_add -:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    import Tkinter as tk
     
    def myevent(e):
        print 'myevent', e.type
     
    root = tk.Tk()
    root.bind('<<foo>>', myevent)
    root.after(500, root.event_generate, '<<foo>>')
    root.mainloop()
    Pour passer des user data à l'event, c'est pas glop (je n'ai pas trouvé l'attribut xyz qui permettre de faire xyz=msg).

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

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

Discussions similaires

  1. Créer des events avec fullcalendar
    Par DjiLow dans le forum jQuery
    Réponses: 7
    Dernier message: 08/02/2011, 23h15
  2. Créer un [Event procédure] sur tous les controles.
    Par SeaWolf601 dans le forum IHM
    Réponses: 9
    Dernier message: 21/01/2009, 16h22
  3. Problème pour créer un Event Handler Feature
    Par Magicmodjo dans le forum SharePoint
    Réponses: 7
    Dernier message: 13/10/2008, 18h26
  4. Créer un Event de rien
    Par Goduak dans le forum Langage
    Réponses: 5
    Dernier message: 16/04/2007, 19h22
  5. [Tkinter] Un petit souçis d'event avec Tkinter
    Par fire.stone dans le forum Tkinter
    Réponses: 4
    Dernier message: 29/10/2005, 21h56

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