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 :

délai d'affichage dans un canevas


Sujet :

Tkinter Python

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Janvier 2017
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Janvier 2017
    Messages : 99
    Points : 26
    Points
    26
    Par défaut délai d'affichage dans un canevas
    Bonjour à tous

    Je cherche comment mettre un délai entre la modification de 2 cercles dans un canevas

    A l'origine j'utilisais un "time.sleep" est ce que le code suivant est plus "propre"

    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
    from tkinter import *
    import time
     
    window = Tk()
    window.geometry("480x360")
    can1 = Canvas(window, bg='dark grey', height=330, width=440)
    can1.pack(expand="YES")
     
    ampoule1 = can1.create_oval(30, 30, 90, 90, width=4, fill='grey')
    ampoule2 = can1.create_oval(30, 110, 90, 170, width=4, fill='grey')
     
    can1.update()
    can1.after(1000)
    can1.itemconfigure(ampoule1, fill='red')
    can1.update()
    can1.after(1000)
    can1.itemconfigure(ampoule2, fill='red')
    can1.update()
     
    window.mainloop()

  2. #2
    Nouveau membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Janvier 2017
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Janvier 2017
    Messages : 99
    Points : 26
    Points
    26
    Par défaut
    Je pense que c'est meux :-)

    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
    from tkinter import *
    import time
     
    window = Tk()
    window.geometry("480x360")
    can1 = Canvas(window, bg='dark grey', height=330, width=440)
    can1.pack(expand="YES")
     
    ampoule1 = can1.create_oval(30, 30, 90, 90, width=4, fill='grey')
    ampoule2 = can1.create_oval(30, 110, 90, 170, width=4, fill='grey')
     
    can1.update()
    can1.after(1000,can1.itemconfigure(ampoule1, fill='red'))
    can1.update()
    can1.after(1000,can1.itemconfigure(ampoule2, fill='red'))
    can1.update()
     
    window.mainloop()

  3. #3
    Membre expérimenté
    Avatar de MPython Alaplancha
    Homme Profil pro
    Paysan à 3 francs six sous
    Inscrit en
    Juin 2018
    Messages
    870
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Paysan à 3 francs six sous
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Juin 2018
    Messages : 870
    Points : 1 522
    Points
    1 522
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par tm68780 Voir le message
    Je pense que c'est meux :-)
    Bonjour,
    Avec la programation évenementiel il n'est pas nécessaire d'utiliser la méthode update.
    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
    from tkinter import *
    import time
     
    window = Tk()
    window.geometry("480x360")
    can1 = Canvas(window, bg='dark grey', height=330, width=440)
    can1.pack(expand="YES")
     
    ampoule1 = can1.create_oval(30, 30, 90, 90, width=4, fill='grey')
    ampoule2 = can1.create_oval(30, 110, 90, 170, width=4, fill='grey')
     
    def action(ampoule,fill):
        can1.itemconfigure(ampoule, fill=fill)
     
    can1.after(1000,lambda :action(ampoule1,'red')) 
    can1.after(2000, lambda :action(ampoule2,'red'))
     
    window.mainloop()
    #Rien de nouveau sous le soleil, tout est vanité comme courir après le vent!
    Developpement pour Android avec Python3/Kivy/Buildozer

  4. #4
    Nouveau membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Janvier 2017
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Janvier 2017
    Messages : 99
    Points : 26
    Points
    26
    Par défaut
    Merci pour la réponse

    en regardant la description de la fonction lambda (fonction anonyme) je ne vois pas le rapport avec le rafraichissement du canevas qui se fait.
    Et pourtant avec la même fonction sans "lambda" le rafraichissement du canevas ne se fait pas.

    https://python.developpez.com/cours/..._functions.php

  5. #5
    Membre expérimenté
    Avatar de MPython Alaplancha
    Homme Profil pro
    Paysan à 3 francs six sous
    Inscrit en
    Juin 2018
    Messages
    870
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Paysan à 3 francs six sous
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Juin 2018
    Messages : 870
    Points : 1 522
    Points
    1 522
    Billets dans le blog
    4
    Par défaut
    Bonjour,
    La fonction lambda dans le code ne sert qu'à passer des arguments à la fonction appellée par after()... Je l'ai mis afin de te montrer comment on passe un argument à la fonction appelée par after(). Considére ça comme un bonnus .

    ...
    Le but était de te montrer comment ecrire avec after() un code non blocant (qui donc n'utilise pas update(), dont l'utilisation abusive témoigne d'un code mal écrit )
    #Rien de nouveau sous le soleil, tout est vanité comme courir après le vent!
    Developpement pour Android avec Python3/Kivy/Buildozer

  6. #6
    Nouveau membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Janvier 2017
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Janvier 2017
    Messages : 99
    Points : 26
    Points
    26
    Par défaut
    Bonjour à tous,
    Merci pour la réponse

    Citation Envoyé par Hominidé Voir le message
    Bonjour,
    La fonction lambda dans le code ne sert qu'à passer des arguments à la fonction appellée par after()... Je l'ai mis afin de te montrer comment on passe un argument à la fonction appelée par after(). Considére ça comme un bonnus .
    Oui ça je comprends et même d'autres particularités de la fonction.
    Mais ça ne m'explique toujours pas pourquoi l'utilisation d'une fonction anonyme rafraichi le canevas !!!


    Citation Envoyé par Hominidé Voir le message
    Le but était de te montrer comment ecrire avec after() un code non blocant (qui donc n'utilise pas update(), dont l'utilisation abusive témoigne d'un code mal écrit )

    Code avec Lambda le canevas est actualisé
    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
    from tkinter import *
     
    window = Tk()
    window.geometry("480x360")
    can1 = Canvas(window, bg='dark grey', height=330, width=440)
    can1.pack(expand="YES")
     
    ampoule1 = can1.create_oval(30, 30, 90, 90, width=4, fill='grey')
    ampoule2 = can1.create_oval(30, 110, 90, 170, width=4, fill='grey')
     
     
    def action(ampoule, fill):
        can1.itemconfigure(ampoule, fill=fill)
     
     
    can1.after(1000, lambda: action(ampoule1, 'red'))
    can1.after(2000, lambda: action(ampoule2, 'red'))
     
    window.mainloop()
    Code sans Lambda le canevas n'est pas actualisé
    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
    from tkinter import *
    window = Tk()
    window.geometry("480x360")
    can1 = Canvas(window, bg='dark grey', height=330, width=440)
    can1.pack(expand="YES")
     
    ampoule1 = can1.create_oval(30, 30, 90, 90, width=4, fill='grey')
    ampoule2 = can1.create_oval(30, 110, 90, 170, width=4, fill='grey')
     
     
    def action(ampoule, fill):
        can1.itemconfigure(ampoule, fill=fill)
     
     
    can1.after(1000, action(ampoule1, 'red'))
    can1.after(2000, action(ampoule2, 'red'))
     
    window.mainloop()

  7. #7
    Membre expérimenté
    Avatar de MPython Alaplancha
    Homme Profil pro
    Paysan à 3 francs six sous
    Inscrit en
    Juin 2018
    Messages
    870
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Paysan à 3 francs six sous
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Juin 2018
    Messages : 870
    Points : 1 522
    Points
    1 522
    Billets dans le blog
    4
    Par défaut
    La syntaxe de la méthode after est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    widget.after(delais_ms, fonction)
    et non widget.after(delais_ms, fonction())
    C'est pourquoi si on veut passer des arguments à fonction, on utilise une fonction lambda .
    #Rien de nouveau sous le soleil, tout est vanité comme courir après le vent!
    Developpement pour Android avec Python3/Kivy/Buildozer

  8. #8
    Nouveau membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Janvier 2017
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Janvier 2017
    Messages : 99
    Points : 26
    Points
    26
    Par défaut
    Désolé je crois que ça ne répond pas à ma question

    De plus l'emploi d'une fonction lambda n'est pas une nécessité, il doit y avoir un autre moyen de se passer du "Update()".

  9. #9
    Membre expérimenté
    Avatar de MPython Alaplancha
    Homme Profil pro
    Paysan à 3 francs six sous
    Inscrit en
    Juin 2018
    Messages
    870
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Paysan à 3 francs six sous
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Juin 2018
    Messages : 870
    Points : 1 522
    Points
    1 522
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par tm68780 Voir le message
    Désolé je crois que ça ne répond pas à ma question
    Désolé, je ne dois pas être très pédagogue...

    Citation Envoyé par tm68780 Voir le message

    De plus l'emploi d'une fonction lambda n'est pas une nécessité, il doit y avoir un autre moyen de se passer du "Update()".
    C'est la structure du code qui me permet de me passer de update, rien avoir avec lambda(redite).. La fonction lambda me permet juste de passer des arguments à la fonction (la méthode after accepte juste le nom de la fonction a appeller -->redite)
    #Rien de nouveau sous le soleil, tout est vanité comme courir après le vent!
    Developpement pour Android avec Python3/Kivy/Buildozer

  10. #10
    Nouveau membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Janvier 2017
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Janvier 2017
    Messages : 99
    Points : 26
    Points
    26
    Par défaut
    Citation Envoyé par Hominidé Voir le message
    Désolé, je ne dois pas être très pédagogue...

    C'est la structure du code qui me permet de me passer de update, rien avoir avec lambda(redite).. La fonction lambda me permet juste de passer des arguments à la fonction (la méthode after accepte juste le nom de la fonction a appeller -->redite)
    Et moi je n'ai pas encore le niveau...

    Donc OK c'est cette structure contrairement à l'autre qui redonne la main au mainloop.
    Mais pourquoi ?

  11. #11
    Nouveau membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Janvier 2017
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Janvier 2017
    Messages : 99
    Points : 26
    Points
    26
    Par défaut
    un parallèle

    Si j'utilise un bouton pour modifier un widget, l'appui sur le bouton va générer un événement
    Par cette événement je pourrais lancer le code qui modifie le widget.
    Après l’exécution de ce code la main est redonnée au widget

    Donc il me faudrait un événement

  12. #12
    Membre expérimenté
    Avatar de MPython Alaplancha
    Homme Profil pro
    Paysan à 3 francs six sous
    Inscrit en
    Juin 2018
    Messages
    870
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Paysan à 3 francs six sous
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Juin 2018
    Messages : 870
    Points : 1 522
    Points
    1 522
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par tm68780 Voir le message
    Et moi je n'ai pas encore le niveau...

    Donc OK c'est cette structure contrairement à l'autre qui redonne la main au mainloop.
    Mais pourquoi ?
    Ce que j'ai dit au sujet de l'emploi de lambda pour passer les arguments à la fonction callback est érroné (ma confusion est liée à l'utilisation de command avec Button)
    Les arguments se passent comme ci dessous:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    widget.after(1000, fonction, arguments)
    #Rien de nouveau sous le soleil, tout est vanité comme courir après le vent!
    Developpement pour Android avec Python3/Kivy/Buildozer

  13. #13
    Nouveau membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Janvier 2017
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Janvier 2017
    Messages : 99
    Points : 26
    Points
    26
    Par défaut
    Dans le cours de Gérard Swinnen chapitre 20-D-2 - Temporisation des animations à l'aide de time.sleep()

    Au coeur de chacune de ces boucles, vous devez cependant toujours veiller à insérer une temporisation pendant
    laquelle vous « rendez la main » au système d'exploitation (afin qu'il puisse s'occuper des autres threads).
    Pour ce faire, vous ferez appel à la fonction sleep() du module time. Cette fonction permet de suspendre l'exécution du
    thread courant pendant un certain intervalle de temps, pendant lequel les autres threads et applications continuent à
    fonctionner. La temporisation ainsi produite ne dépend pas de mainloop(), et par conséquent, elle peut être beaucoup
    plus courte que celle que vous autorise la méthode after().

    Donc dans le cas où l'on a une partie séquentielle de modification de widget le "sleep" serait apparemment la meilleure solution

  14. #14
    Expert éminent
    Avatar de transgohan
    Homme Profil pro
    Développeur Temps réel Embarqué
    Inscrit en
    Janvier 2011
    Messages
    3 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Temps réel Embarqué

    Informations forums :
    Inscription : Janvier 2011
    Messages : 3 146
    Points : 9 386
    Points
    9 386
    Par défaut
    Mauvaise interprétation du fonctionnement de lambda et des paramètre attendus de la fonction after.

    Une lambda :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    can1.after(1000, lambda: action(ampoule1, 'red'))
    Se transforme en quelque chose de ce genre à l'exécution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    def ma_lambda():
      action(ampoule1, 'red')
     
    ...
     
    can1.after(1000, ma_lambda)
    On passe donc un type "function" à la fonction after.

    Quand vous faites :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    can1.after(1000, action(ampoule1, 'red'))
    Vous passez le retour de l'exécution de la fonction action à la fonction after.
    Pour expliciter si action avait un "return 1" vous pouvez transformer le code en :

    « Toujours se souvenir que la majorité des ennuis viennent de l'espace occupé entre la chaise et l'écran de l'ordinateur. »
    « Le watchdog aboie, les tests passent »

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

    Citation Envoyé par tm68780 Voir le message
    Oui ça je comprends et même d'autres particularités de la fonction.
    Mais ça ne m'explique toujours pas pourquoi l'utilisation d'une fonction anonyme rafraichi le canevas !!!
    Pour comprendre, il faut décortiquer les instructions.

    Si f est une fonction a = fassigne l'objet f à la variable a alors que a = f() exécute la fonction f et assigne le retour à a.

    Ça s'applique dans tous les contexte et tout particulièrement celui d'after: un callback est un objet fonction et non le résultat de l'appel de la fonction.

    Le comportement de la séquence:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ...after(1000, f())
    ...after(2000, f())
    ...mainloop()
    s'explique par le fait que f retournant None, .after se comporte comme time.sleep(...).

    Après il faut avoir intégrer le concept de boucle évènementielle pour comprendre que les évènements ne seront pris en compte (et on verra des changement) que lorsqu'on vide les évènements en attente.
    Sans appel à .update dans cette séquence, çà attendra l'arrivée dans .mainloop et on verra le résultat final sans voir les états intermédiaires!

    Reste le soucis d'appel du callback avec des arguments: si on veut qu'elle ne soit pas appelée tout de suite, il faut fabriquer une fonction qui appellera cette fonction là avec les paramètres choisis.

    La closure fabriquée en interne par .after ne supporte que le passage d'arguments positionnels (on peut écrire .after(..., f, a, b) pour appeler f(a, b)).

    Par contre avec des keywords comme pour .itemconfigure(x, fill=...), il faudra faire autrement: lambda, closure, autre fonction qui ne prend que des paramètre positionnel et emballe l'appel à .itemconfigure,...

    Citation Envoyé par tm68780 Voir le message
    Dans le cours de Gérard Swinnen chapitre 20-D-2 - Temporisation des animations à l'aide de time.sleep()
    Vous plongez la tête dans le chapitre 20 alors que vous n'avez pas pris le temps d'assimiler les chapitres précédents.
    Pour comprendre ce que ces mots veulent dire, il faut que vous sachiez les traduire en contexte et en code. Pour çà il faut avoir de l'expérience (et l'expérience vient avec le temps).

    Relisez ces paragraphes dans quelques temps, vous les comprendrez avec un autre éclairage (celui de votre expérience) et différemment.

    C'est ce qui fait tout l'intérêt d'une documentation ou d'un tuto.: on peut relire quelque chose qu'on avait cru comprendre et se rendre compte du sens de certains mots dans le contexte qui a motivé cette relecture.

    L'autre intérêt est qu'il y a des exercices corrigés.

    Donc avant de partir à vouloir écrire vos propres codes pour vous retrouver surpris de certains comportements, alors que normalement, vous devriez avoir pris le temps de potasser ces sujets dans un tuto avant de poster.

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

  16. #16
    Nouveau membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Janvier 2017
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Janvier 2017
    Messages : 99
    Points : 26
    Points
    26
    Par défaut
    Merci beaucoup aux intervenants, j'ai compris certaines choses.

  17. #17
    Nouveau membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Janvier 2017
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Janvier 2017
    Messages : 99
    Points : 26
    Points
    26
    Par défaut
    Bonjour à tous

    Avec les informations reçues j'ai comparé les 2 codes suivants:

    Le 1er avec une fonction Lambda:
    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
    #  -------------------- En utilisant une fonction LAMDBA
    from tkinter import *
    window = Tk()
    window.geometry("480x360")
    can1 = Canvas(window, bg='dark grey', height=330, width=440)
    can1.pack(expand="YES")
    ampoule1 = can1.create_oval(30, 30, 90, 90, width=4, fill='grey')
    ampoule2 = can1.create_oval(30, 110, 90, 170, width=4, fill='grey')
     
    def action(ampoule, fill):
        can1.itemconfigure(ampoule, fill=fill)
     
    can1.after(1000, lambda: action(ampoule1, 'red'))       # Ici after reçoit le retour de action
     
    # instruction précédente se transforme à l'exécution en :
    #def action():
    #    action(ampoule1, 'red')
    #can1.after(1000, action)                               # Ici after reçoit fa fonction action
     
    can1.after(2000, lambda: action(ampoule2, 'red'))       # Ici after reçoit la fonction action
     
    window.mainloop()
    Le 2eme sans fonction Lambda et qui tel quel a besoin d'un Update() et si j'ai bien compris c'est parce-que:
    can1.after(1000, action(ampoule1, 'red')) after ne reçoit pas la fonction mas le résultat de la fonction action

    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
    #  -------------------- Sans utiliser de fonction LAMDBA
    from tkinter import *
    window = Tk()
    window.geometry("480x360")
    can1 = Canvas(window, bg='dark grey', height=330, width=440)
    can1.pack(expand="YES")
    ampoule1 = can1.create_oval(30, 30, 90, 90, width=4, fill='grey')
    ampoule2 = can1.create_oval(30, 110, 90, 170, width=4, fill='grey')
     
    def action(ampoule, couleur):
        can1.itemconfigure(ampoule, fill=couleur)
     
    can1.after(1000, action(ampoule1, 'red'))      # Ici after reçoit le résulat de la fonction action
    can1.update()                                  # Update nécéssaire
    can1.after(1000, action(ampoule2, 'red'))      # Ici after reçoit le résulat de la fonction action
     
    window.mainloop()
    Pour information j'ai testé la même chose avec un bouton de formulaire et là évidement pas besoin d'update vu qu'on retourne au mainloop après l’exécution de l'action

    Toujours si j'ai bien lu et compris, une fonction Lambda n'est pas obligatoire, il y a moyen de sans passer

    La question comment

  18. #18
    Expert éminent
    Avatar de transgohan
    Homme Profil pro
    Développeur Temps réel Embarqué
    Inscrit en
    Janvier 2011
    Messages
    3 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Temps réel Embarqué

    Informations forums :
    Inscription : Janvier 2011
    Messages : 3 146
    Points : 9 386
    Points
    9 386
    Par défaut
    Oui enfin non...
    Ton second code est... Faux... Même s'il obtient le résultat que tu veux...

    Pour ne pas écrire n'importe quoi il faudrait plutôt faire ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    action(ampoule1, 'red')
    Time.sleep(1000)
    can1.update()
    Car after ne prend pas un retour de fonction, mais un type function !
    Même si Python est très permissif sur les conversions de type il faut faire attention à ne pas tenter de faire rentrer un avion dans un garage à vélo, il y a des risques de faire tomber des murs.

    « Toujours se souvenir que la majorité des ennuis viennent de l'espace occupé entre la chaise et l'écran de l'ordinateur. »
    « Le watchdog aboie, les tests passent »

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

    Citation Envoyé par tm68780 Voir le message
    La question comment
    Si vous aviez pu comprendre tout ce qu'on a essayé de vous raconter, vous auriez écrit:
    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
    from tkinter import *
    window = Tk()
    window.geometry("480x360")
    can1 = Canvas(window, bg='dark grey', height=330, width=440)
    can1.pack(expand="YES")
    ampoule1 = can1.create_oval(30, 30, 90, 90, width=4, fill='grey')
    ampoule2 = can1.create_oval(30, 110, 90, 170, width=4, fill='grey')
     
    def action(ampoule, couleur):
        can1.itemconfigure(ampoule, fill=couleur)
     
    can1.after(1000, action, ampoule1, 'red')      # Ici after reçoit le résulat de la fonction action
    #can1.update()                                  # Update nécéssaire
    can1.after(2000, action, ampoule2, 'red')      # Ici after reçoit le résulat de la fonction action
     
    window.mainloop()
    Le problème est que vous ne pouvez pas comprendre ce qu'on raconte sans avoir pris le temps d'apprendre les bases...

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

  20. #20
    Nouveau membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Janvier 2017
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Janvier 2017
    Messages : 99
    Points : 26
    Points
    26
    Par défaut
    OK merci j'ai changé l'avion par un ULM, non pas UML

    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
    #  -------------------- En utilisant une fonction LAMDBA
    from tkinter import *
    window = Tk()
    window.geometry("480x360")
    can1 = Canvas(window, bg='dark grey', height=330, width=440)
    can1.pack(expand="YES")
    ampoule1 = can1.create_oval(30, 30, 90, 90, width=4, fill='grey')
    ampoule2 = can1.create_oval(30, 110, 90, 170, width=4, fill='grey')
     
    def action(ampoule, fill):
        can1.itemconfigure(ampoule, fill=fill)
     
    can1.after(1000, lambda: action(ampoule1, 'red'))       # Ici after reçoit le retour de action et dans ce cas NONE
     
    # instruction précédente se transforme à l'exécution en :
    #def action():
    #    action(ampoule1, 'red')
    #can1.after(1000, action)                               # Ici after reçoit la fonction action
     
    can1.after(2000, lambda: action(ampoule2, 'red'))       # Ici after reçoit la fonction action
     
    window.mainloop()
     
    # a=f   Si l'objet f est une fonction a = f assigne l'objet f à la variable a
    # a=f() exécute la fonction f et assigne le retour à a.
    # un callback est un objet fonction et non le résultat de l'appel de la fonction.
    # Ça s'applique dans tous les contexte et tout particulièrement celui d'after
    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
    #  -------------------- Sans utiliser de fonction LAMDBA
    from tkinter import *
    import time
     
    window = Tk()
    window.geometry("480x360")
    can1 = Canvas(window, bg='dark grey', height=330, width=440)
    can1.pack(expand="YES")
    ampoule1 = can1.create_oval(30, 30, 90, 90, width=4, fill='grey')
    ampoule2 = can1.create_oval(30, 110, 90, 170, width=4, fill='grey')
    can1.update()
     
    def action(ampoule, couleur):
        can1.itemconfigure(ampoule, fill=couleur)
     
    """
    can1.after(1000, action(ampoule1, 'red'))      # Ici after reçoit le résulat de la fonction action et dans ce cas NONE
    can1.update()                                  # Update nécéssaire
    can1.after(1000, action(ampoule2, 'red'))      # Ici after reçoit le résulat de la fonction action et dans ce cas NONE
     
    """
    action(ampoule1, 'red')
    can1.update()
    time.sleep(1)
    action(ampoule2, 'red')
    can1.update()
     
    window.mainloop()
     
    # a=f   Si l'objet f est une fonction a = f assigne l'objet f à la variable a
    # a=f() exécute la fonction f et assigne le retour à a.
    # un callback est un objet fonction et non le résultat de l'appel de la fonction.
    # Ça s'applique dans tous les contexte et tout particulièrement celui d'after
    Donc maintenant le but est de se passer de time et d'Update

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [Python 3.X] Tkinter / affichage d'une image dans un canevas
    Par willy31 dans le forum GUI
    Réponses: 5
    Dernier message: 02/01/2018, 08h06
  2. Réponses: 2
    Dernier message: 28/07/2006, 14h29
  3. Réponses: 9
    Dernier message: 02/02/2005, 15h52
  4. affichage dans le front buffers ne marche pas!
    Par jamal24 dans le forum OpenGL
    Réponses: 3
    Dernier message: 22/08/2003, 19h14
  5. Texte dans un canevas
    Par Bernard M dans le forum Langage
    Réponses: 4
    Dernier message: 28/11/2002, 17h56

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