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 :

Comment répéter régulièrement une méthode de classe dans une GUI ?


Sujet :

Tkinter Python

  1. #1
    Membre confirmé Avatar de calogerogigante
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    602
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2003
    Messages : 602
    Points : 497
    Points
    497
    Par défaut Comment répéter régulièrement une méthode de classe dans une GUI ?
    J'ai écrit le code suivant, qui permet de replacer aléatoirement un certain nombre d'étoiles dans un Canvas de Tkinter :

    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
    # -*- coding:utf-8 -*-
    from Tkinter import *
    from random import randrange
    import time
     
    # ==============================================
    # Espace et étoiles
    # Codé sous Windows Xp avec Python 2.6.4.
    # par C. Gigante : http://www.gigante.be/python/
    # Janvier 2010
    # ==============================================
     
    class Etoile:
        def __init__(self, dir, ray=1, x=0, y=0, dist=1):
            self.x = x
            self.y = y
            self.dir = dir
            self.rayon = ray
            self.dist = dist
     
        def donner_reference(self, refe):
            # contient la référence du cercle tracé sur le canvas espace
            self.ref = refe
     
    class Application:
        def __init__(self):
            self.root=Tk()
            self.root.title('Espace et étoiles')
            self.la = 600
            self.ha = 400
            self.root.geometry(str(self.la)+"x"+str(self.ha))
     
            self.nbreetoiles = 30
     
            # nouvelles coordonnées du centre du canvas :
            self.x0 = self.la/2
            self.y0 = self.ha/2
     
            self.but = Button(self.root, text="Redessiner", command=self.replacer_etoiles)
            self.but.pack(side=BOTTOM)
     
            self.espace = Canvas(self.root, bg="black", width=self.la, height=self.ha)
            self.espace.pack(side=TOP, fill=BOTH, expand=YES)
     
            self.lesetoiles = []
            # création des étoiles :
            for i in range(1,self.nbreetoiles):
                xx, yy, direction, rayo = randrange(self.la), randrange(self.ha), randrange(360), randrange(10)
                et = Etoile(direction,rayo,xx,yy,1)
                ref_et = self.espace.create_oval(xx-rayo,yy-rayo,xx+rayo,yy+rayo,tag=str(i), fill="yellow")
                et.donner_reference(ref_et)
                self.lesetoiles.append(et)
     
            self.root.mainloop()
     
        def replacer_etoiles(self):
            for i in range(1,self.nbreetoiles):
                xx, yy, direction, rayo = randrange(self.la), randrange(self.ha), randrange(360), randrange(10)
                self.espace.coords(str(i),xx-rayo,yy-rayo,xx+rayo,yy+rayo)
     
    # départ du programme principal :
    if __name__ == '__main__':
        app = Application()
    Le programme marche très bien, mais ce que je voudrais, c'est supprimer le bouton "Redessiner" et faire en sorte que la méthode self.replacer_etoiles() soit appelée automatiquement toutes les 2 secondes.

    Je ne vois pas comment faire ?

    Est-il possible de faire cela en évitant d'utiliser les threads ?

  2. #2
    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 calogerogigante,

    Pas possible avec le mainloop, utilise un Toplevel qui n'en a pas :
    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
     
    # -*- coding:utf-8 -*-
    from Tkinter import *
    from random import randrange
    import time
     
    # ==============================================
    # Espace et étoiles
    # Codé sous Windows Xp avec Python 2.6.4.
    # par C. Gigante : http://www.gigante.be/python/
    # Janvier 2010
    # ==============================================
     
    class Etoile:
        def __init__(self, dir, ray=1, x=0, y=0, dist=1):
            self.x = x
            self.y = y
            self.dir = dir
            self.rayon = ray
            self.dist = dist
     
        def donner_reference(self, refe):
            # contient self.la référence du cercle tracé sur le canvas espace
            self.ref = refe
     
    class Application:
        def __init__(self):
            self.root=Tk()
            self.root.withdraw()
            self.Graphique()
            self.root.update()
            try:
                while 1:
                    for i in range(1,self.nbreetoiles):
                        xx, yy, direction, rayo = randrange(self.la), randrange(self.ha), randrange(360), randrange(10)
                        self.espace.coords(str(i),xx-rayo,yy-rayo,xx+rayo,yy+rayo)
                    self.root.after(240, self.root.update())
            except KeyboardInterrupt:
                # A revoir
                self.destroy()
            self.root.mainloop()
     
        def Graphique(self):
            self.mafenetre=Toplevel()
            self.mafenetre.title('Espace et étoiles')
            self.la = 600
            self.ha = 400
            self.mafenetre.geometry(str(self.la)+"x"+str(self.ha))
     
            self.nbreetoiles = 30
     
            # nouvelles coordonnées du centre du canvas :
            x0 = self.la/2
            y0 = self.ha/2
     
            self.espace = Canvas(self.mafenetre, bg="black", width=self.la, height=self.ha)
            self.espace.pack(side=TOP, fill=BOTH, expand=YES)
     
            lesetoiles = []
            # création des étoiles :
            for i in range(1,self.nbreetoiles):
                xx, yy, direction, rayo = randrange(self.la), randrange(self.ha), randrange(360), randrange(10)
                et = Etoile(direction,rayo,xx,yy,1)
                ref_et = self.espace.create_oval(xx-rayo,yy-rayo,xx+rayo,yy+rayo,tag=str(i), fill="yellow")
                et.donner_reference(ref_et)
                lesetoiles.append(et)
     
    # départ du programme principal :
    if __name__ == '__main__':
        app = Application()
    @+
    Merci d'utiliser le forum pour les questions techniques.

  3. #3
    Membre confirmé Avatar de calogerogigante
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    602
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2003
    Messages : 602
    Points : 497
    Points
    497
    Par défaut
    Merci PauseKawa pour ton précieux conseil :

    Je ne connaissais pas self.root.withdraw() et self.root.update() dans le contexte d'un TopLevel()...

    Tu me rassures en me disant que, avec le mainloop(), ça bloquait de façon structurelle, dans le cas où je ne veux pas (encore) utiliser les threads que je ne connais pas bien...

    Merci, merci, je vais analyser tout ça !!!!


  4. #4
    Membre confirmé Avatar de calogerogigante
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    602
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2003
    Messages : 602
    Points : 497
    Points
    497
    Par défaut
    J'ai rajouté une interception de fermeture de la fenetre TopLevel() pour utiliser un flag qui évite de refaire une exécution de la fonction self.replacer quand la TopLevel est détruite (cela génèrait un vilain message d'erreur quand on quittait le programme...)

    J'ai donc modifié encore le code pour avoir un truc encore 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
    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
    # -*- coding:utf-8 -*-
    from Tkinter import *
    from random import randrange
    import time
    import sys
     
    # ==============================================
    # Espace et étoiles
    # Codé sous Windows Xp avec Python 2.6.4.
    # par C. Gigante : http://www.gigante.be/python/
    # Janvier 2010
    # ==============================================
     
    class Etoile:
        def __init__(self, dir, ray=1, x=0, y=0, dist=1):
            self.x = x
            self.y = y
            self.dir = dir
            self.rayon = ray
            self.dist = dist
        def donner_reference(self, refe):
            # contient la référence du cercle tracé sur le canvas espace
            self.ref = refe
     
     
    class Application:
        def __init__(self):
            self.root=Tk()
            # on cache la fenêtre principale, mère de toutes les autres
            self.root.withdraw()
            self.Graphique()
            while (self.flag_loop == 1):
                self.replacer()
     
            self.root.mainloop()
     
        def replacer(self):
            for i in range(1,self.nbreetoiles):
                xx, yy, direction, rayo = randrange(self.la), randrange(self.ha), randrange(360), randrange(10)
                self.espace.coords(str(i),xx-rayo,yy-rayo,xx+rayo,yy+rayo)
            self.root.after(120, self.root.update())
     
        def Graphique(self):
            self.mafenetre=Toplevel()
            self.mafenetre.title('Espace et étoiles')
            self.flag_loop = 1
            self.mafenetre.protocol("WM_DELETE_WINDOW", self.detruire)
     
            self.la = 600
            self.ha = 400
            self.mafenetre.geometry(str(self.la)+"x"+str(self.ha))
     
            self.nbreetoiles = 30
     
            # nouvelles coordonnées du centre du canvas :
            x0 = self.la/2
            y0 = self.ha/2
     
            self.espace = Canvas(self.mafenetre, bg="black", width=self.la, height=self.ha)
            self.espace.pack(side=TOP, fill=BOTH, expand=YES)
     
            lesetoiles = []
            # création des étoiles :
            for i in range(1,self.nbreetoiles):
                xx, yy, direction, rayo = randrange(self.la), randrange(self.ha), randrange(360), randrange(10)
                et = Etoile(direction,rayo,xx,yy,1)
                ref_et = self.espace.create_oval(xx-rayo,yy-rayo,xx+rayo,yy+rayo, tag=str(i), fill="yellow")
                et.donner_reference(ref_et)
                lesetoiles.append(et)
     
        def detruire(self):
            print "On detruit la TopLevel()..."
            self.flag_loop = 0 # pour empêcher le dernier loop quand la TopLevel() est détruite
            self.mafenetre.destroy()
            sys.exit()
     
    # départ du programme principal :
    if __name__ == '__main__':
        app = Application()
    Merci en tout cas, j'approche de mon objectif grâce à ton explication claire et à la réflexion enrichissante qu'elle a engendrée dans ma tête !

  5. #5
    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
    Bonjour,

    Citation Envoyé par calogerogigante Voir le message
    Je ne connaissais pas self.root.withdraw() et self.root.update() dans le contexte d'un TopLevel()...
    Désolé pour le self.root.update(). J'avais laisser cela d'un test précédent

    Merci pour le flag : j'avais la flegme

    Sinon pour l'histoire des threads c'est tout simple. Un exemple ou le pid du script qui lance est passé en agrv. Tant que le pid existe le canvas est mis a jour :

    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
    #!/usr/bin/env python
    # -*- coding: ISO8859-1 -*-
    #
    #
    from Tkinter import *
    import threading
    import os
    from sys import argv, stdout
    from subprocess import Popen, PIPE
     
    class Maj_Globals():
        wiBarre = None
        IndRecherche = 0
     
    class Update_MaFenetre(threading.Thread):
        def __init__(self):
            threading.Thread.__init__(self)
            self._stopevent = threading.Event( )
     
        def run(self):
            while not self._stopevent.isSet():
                self._stopevent.wait(0.2)
                Maj_Globals.IndRecherche += 1
                if Maj_Globals.IndRecherche == 190: Maj_Globals.IndRecherche = 0
                Maj_Globals.wiBarre.TmpAttendCanvas.coords(Maj_Globals.wiBarre.BarreBleu, (Maj_Globals.IndRecherche, 0, 20 + Maj_Globals.IndRecherche, 21))
                Monps = Popen(['ps', '-e'], stdout=PIPE)
                Mongrep = Popen(['grep', str(argv[1])], stdin=Monps.stdout, stdout=PIPE)
                attentefin = Mongrep.communicate()[0]
                if not attentefin: self._stopevent.set()
            os._exit(0)
     
    class GUI(Tk):
        def __init__(self):
            Tk.__init__(self)
            self.withdraw()
            Maj_Globals.wiBarre = Toplevel()
            Maj_Globals.wiBarre.overrideredirect(1)
            Maj_Globals.wiBarre.geometry("%dx%d+%d+%d" % (200,90, (Maj_Globals.wiBarre.winfo_screenwidth()-200)/2, (Maj_Globals.wiBarre.winfo_screenheight()-90)/2 ) )
            BordureTmpAttend = Frame(Maj_Globals.wiBarre, bd=2, relief=GROOVE)
            BordureTmpAttend.place(x=1, y=1, relwidth = 1, relheight = 1, bordermode='inside')
            Label(BordureTmpAttend, fg = 'red', text = os.linesep + "Téléchargement en cours..." + os.linesep).pack(side=TOP)
            Maj_Globals.wiBarre.TmpAttendCanvas = Canvas(BordureTmpAttend, height=20, width=180, bg='white', bd=2, relief=SUNKEN)
            Maj_Globals.wiBarre.TmpAttendCanvas.pack(side=TOP)
            Maj_Globals.wiBarre.BarreBleu = Maj_Globals.wiBarre.TmpAttendCanvas.create_rectangle((0, 0, 20 + 0, 21), outline='#2a7aff',fill='#2a7aff', width=2)
            Maj_Globals.wiBarre.update()
            Update_MaFenetre().start()
     
    if __name__=='__main__':
        test=GUI()
        test.mainloop()
    Merci d'utiliser le forum pour les questions techniques.

  6. #6
    Membre confirmé Avatar de calogerogigante
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    602
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2003
    Messages : 602
    Points : 497
    Points
    497
    Par défaut
    Merci pour tes infos supplémentaires, PauseKawa, je vais y jeter un oeil attentif dans la journée...

    En attendant, regarde le beau déplacement spatial, à travers les étoiles, que j'ai pu terminer grâce à ton aide :

    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
    82
    83
    84
    85
    86
    87
    88
    89
    # -*- coding:utf-8 -*-
    from Tkinter import *
    from random import randrange
    import time
    import sys
     
    # ==============================================
    # Espace et étoiles
    # Codé sous Windows Xp avec Python 2.6.4.
    # par C. Gigante : http://www.gigante.be/python/
    # Janvier 2010
    # ==============================================
     
    class Etoile:
        def __init__(self, dir, ray=1, x=0, y=0, dist=1):
            self.x = x
            self.y = y
            self.dir = dir
            self.rayon = ray
            self.dist = dist
        def donner_reference(self, refe):
            # contient la référence du cercle tracé sur le canvas espace
            self.reference = refe
     
     
    class Application:
        def __init__(self):
            self.root=Tk()
            self.r_max = 10
            # on cache la fenêtre principale, mère de toutes les autres
            self.root.withdraw()
            self.Graphique()
            while (self.flag_loop == 1):
                self.replacer()
     
            self.root.mainloop()
     
        def replacer(self):
            for etoi in self.lesetoiles:
                xxx = int(etoi.x)
                yyy = int(etoi.y)
                if (xxx > self.la):
                    xxx = 0
                    yyy = randrange(self.ha)
                    etoi.rayon = randrange(1,self.r_max)
                r = int(etoi.rayon)
                xxx = xxx + (r * 1.5)
                etoi.x = xxx
                etoi.y = yyy
                self.espace.coords(etoi.reference ,xxx-r, yyy-r, xxx+r, yyy+r)
            self.root.after(50, self.root.update())
     
        def Graphique(self):
            self.mafenetre=Toplevel()
            self.mafenetre.title('Espace et étoiles')
            self.flag_loop = 1
            self.mafenetre.protocol("WM_DELETE_WINDOW", self.detruire)
     
            self.la = 800
            self.ha = 600
            self.mafenetre.geometry(str(self.la)+"x"+str(self.ha))
     
            self.nbreetoiles = 50
     
            # nouvelles coordonnées du centre du canvas :
            x0 = self.la/2
            y0 = self.ha/2
     
            self.espace = Canvas(self.mafenetre, bg="black", width=self.la, height=self.ha)
            self.espace.pack(side=TOP, fill=BOTH, expand=YES)
     
            self.lesetoiles = []
            # création des étoiles :
            for i in range(1,self.nbreetoiles):
                xx, yy, direction, rayo = randrange(self.la), randrange(self.ha), randrange(360), randrange(1,self.r_max)
                et = Etoile(direction,rayo,xx,yy,1)
                ref_et = self.espace.create_oval(xx-rayo,yy-rayo,xx+rayo,yy+rayo, tag=str(i), fill="grey")
                et.donner_reference(ref_et)
                self.lesetoiles.append(et)
     
        def detruire(self):
            print "On detruit la TopLevel()..."
            self.flag_loop = 0 # pour empêcher le dernier loop quand la TopLevel() est détruite
            self.mafenetre.destroy()
            sys.exit()
     
    # départ du programme principal :
    if __name__ == '__main__':
        app = Application()
    J'ajouterais bientôt cet exemple sur mon site personnel consacré au python, dans la partie didacticiel !

  7. #7
    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
    Bonjour,

    Je me demande ce que les autres ont avec pygame... un simple canvas et voili

    Ceci dit cela manque de grandeur pour un espace sidéral...

    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
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from Tkinter import *
    from random import randrange
    import time
    import sys
     
    # ==============================================
    # Espace et étoiles
    # Codé sous Windows Xp avec Python 2.6.4.
    # par C. Gigante : http://www.gigante.be/python/
    # Janvier 2010
    # ==============================================
     
    class Etoile:
        def __init__(self, dir, ray=1, x=0, y=0, dist=1):
            self.x = x
            self.y = y
            self.dir = dir
            self.rayon = ray
            self.dist = dist
     
        def donner_reference(self, refe):
            # contient la référence du cercle tracé sur le canvas espace
            self.reference = refe
     
     
    class Application:
        def __init__(self):
            self.root=Tk()
            self.r_max = 10
            # on cache la fenêtre principale, mère de toutes les autres
            self.root.withdraw()
            self.Graphique()
            while (self.flag_loop == 1):
                self.replacer()
            self.root.mainloop()
     
        def replacer(self):
            # Avec except KeyboardInterrupt pour eviter une erreur sur ctrl+c
            try:
                while self.flag_loop == 1:
                    for etoi in self.lesetoiles:
                        xxx = int(etoi.x)
                        yyy = int(etoi.y)
                        if (xxx > self.la):
                            xxx = 0
                            yyy = randrange(self.ha)
                            etoi.rayon = randrange(1,self.r_max)
                        r = int(etoi.rayon)
                        xxx = xxx + (r * 1.5)
                        etoi.x = xxx
                        etoi.y = yyy
                        self.espace.coords(etoi.reference ,xxx-r, yyy-r, xxx+r, yyy+r)
                    self.root.after(50, self.root.update())
            except KeyboardInterrupt:
                self.detruire()
     
        def Graphique(self):
            self.mafenetre=Toplevel()
            self.mafenetre.title('Espace et étoiles')
            self.flag_loop = 1
            self.mafenetre.protocol("WM_DELETE_WINDOW", self.detruire)
     
            # Recuperation de l'affichage
            self.la = self.root.winfo_screenwidth()
            self.ha = self.root.winfo_screenheight()
     
            self.mafenetre.geometry(str(self.la)+"x"+str(self.ha))
     
            self.nbreetoiles = 100
     
            # nouvelles coordonnées du centre du canvas :
            x0 = self.la/2
            y0 = self.ha/2
     
            self.espace = Canvas(self.mafenetre, bg="black", width=self.la, height=self.ha)
            self.espace.pack(side=TOP, fill=BOTH, expand=YES)
     
            # Bind du clic gauche pour fermer.
            self.espace.bind('<ButtonRelease-1>', self.detruire)
     
            # Outrepasse le decorateur
            self.mafenetre.overrideredirect(1)
     
            self.lesetoiles = []
            # création des étoiles :
            for i in range(1,self.nbreetoiles):
                xx, yy, direction, rayo = randrange(self.la), randrange(self.ha), randrange(360), randrange(1,self.r_max)
                et = Etoile(direction,rayo,xx,yy,1)
                ref_et = self.espace.create_oval(xx-rayo,yy-rayo,xx+rayo,yy+rayo, tag=str(i), fill="grey")
                et.donner_reference(ref_et)
                self.lesetoiles.append(et)
     
        def detruire(self, event=None):
            # event = None car bind retourne un event
            print ("On detruit la TopLevel()...")
            self.flag_loop = 0 # pour empêcher le dernier loop quand la TopLevel() est détruite
            self.mafenetre.destroy()
            sys.exit(0)
     
    # départ du programme principal :
    if __name__ == '__main__':
        app = Application()
    @+
    Merci d'utiliser le forum pour les questions techniques.

  8. #8
    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
    Bonjour,

    Quelques raffinements...

    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
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from Tkinter import *
    from random import randrange
    import time
    import sys
     
    # ==============================================
    # Espace et étoiles
    # Codé sous Windows Xp avec Python 2.6.4.
    # par C. Gigante : http://www.gigante.be/python/
    # Janvier 2010
    # ==============================================
     
    class Etoile:
        def __init__(self, dir, ray=1, x=0, y=0, dist=1):
            self.x = x
            self.y = y
            self.dir = dir
            self.rayon = ray
            self.dist = dist
     
        def donner_reference(self, refe):
            # contient la référence du cercle tracé sur le canvas espace
            self.reference = refe
     
     
    class Application:
        def __init__(self):
            self.root=Tk()
            self.r_max = 10
            # on cache la fenêtre principale, mère de toutes les autres
            self.root.withdraw()
            self.Graphique()
            while (self.flag_loop == 1):
                self.replacer()
            self.root.mainloop()
     
        def replacer(self):
            # Avec except KeyboardInterrupt pour eviter une erreur sur ctrl+c
            try:
                while self.flag_loop == 1:
                    for etoi in self.lesetoiles:
                        xxx = int(etoi.x)
                        yyy = int(etoi.y)
                        if (xxx > self.la):
                            xxx = 0
                            yyy = randrange(self.ha)
                            etoi.rayon = randrange(1,self.r_max)
                        r = int(etoi.rayon)
                        xxx = xxx + (r * 1.5)
                        etoi.x = xxx
                        etoi.y = yyy
                        self.espace.coords(etoi.reference ,xxx-r, yyy-r, xxx+r, yyy+r)
                    self.root.after(50, self.root.update())
            except KeyboardInterrupt:
                self.detruire()
     
        def Graphique(self):
            self.flag_affichage = 1
            self.flag_loop = 1
            self.la, self.ha = 0, 0
     
            self.mafenetre=Toplevel()
            self.mafenetre.title('Espace et étoiles')
            self.mafenetre.protocol("WM_DELETE_WINDOW", self.detruire)
     
            self.nbreetoiles = 100
     
            # nouvelles coordonnées du centre du canvas :
            self.x0 = self.la/2
            self.y0 = self.ha/2
     
            self.espace = Canvas(self.mafenetre, bg="black", width=self.la, height=self.ha)
            self.espace.pack(side=TOP, fill=BOTH, expand=YES)
     
            self.modif_affichage()
     
            # Bind du clic gauche pour fermer et du clic droit pour modifier l'affichage.
            self.espace.bind('<ButtonRelease-1>', self.detruire)
            self.espace.bind('<ButtonRelease-3>', self.modif_affichage)
     
        def creation_etoiles(self):
            self.lesetoiles = []
            # création des étoiles :
            for i in range(1,self.nbreetoiles):
                xx, yy, direction, rayo = randrange(self.la), randrange(self.ha), randrange(360), randrange(1,self.r_max)
                et = Etoile(direction,rayo,xx,yy,1)
                ref_et = self.espace.create_oval(xx-rayo,yy-rayo,xx+rayo,yy+rayo, tag=str(i), fill="grey")
                et.donner_reference(ref_et)
                self.lesetoiles.append(et)
     
        def detruire(self, event=None):
            # event = None car bind retourne un event
            print ("On detruit la TopLevel()...")
            self.flag_loop = 0 # pour empêcher le dernier loop quand la TopLevel() est détruite
            self.mafenetre.destroy()
            sys.exit(0)
     
        def modif_affichage(self, event = None):
            # self.flag_affichage == 0 : Mode fenètre
            # self.flag_affichage == 1 : Plein écran
            if self.flag_affichage == 0:
                self.flag_affichage = 1
                self.la = self.root.winfo_screenwidth()
                self.ha = self.root.winfo_screenheight()
                self.mafenetre.geometry(str(self.la)+"x"+str(self.ha))
            elif self.flag_affichage == 1:
                self.flag_affichage = 0
                self.la = 800
                self.ha = 600
                self.mafenetre.geometry("%dx%d+%d+%d" % (self.la,self.ha,(self.root.winfo_screenwidth()-self.la)/2, (self.root.winfo_screenheight()-self.ha)/2))
            self.espace.delete(ALL)
            self.creation_etoiles()
     
    # départ du programme principal :
    if __name__ == '__main__':
        app = Application()
    @+
    Merci d'utiliser le forum pour les questions techniques.

  9. #9
    Membre confirmé Avatar de calogerogigante
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    602
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2003
    Messages : 602
    Points : 497
    Points
    497
    Par défaut
    J'ai essayé de faire le point sur cette méthode présentée ci-dessus pour animer "simplement" et "régulièrement" les dessins dans un canvas.

    Voici un programme épuré, avec une seule boule, qui essaie de montrer l'essentiel de cette technique :

    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
    # -*- coding:utf-8 -*-
    from Tkinter import *
    from random import randrange
    import time
    import sys
     
    # ==============================
    # Animation - avec Python 2.6.4.
    # ==============================
     
    class Application:
        def __init__(self):
            self.root=Tk()
            self.rayon = 20
            self.duree = 50 # en milli secondes
            self.move = 20 # en pixels
            # on cache la fenêtre principale
            self.root.withdraw()
            self.Fenetre()
            while (self.flag_loop == 1):
                self.redessiner()
            self.root.mainloop()
     
        def redessiner(self):
            self.x = self.x + randrange(-self.move, self.move)
            self.y = self.y + randrange(-self.move, self.move)
            if ( self.x > self.la):
                self.x = self.la
            if ( self.x < 0):
                self.x = 0
            if ( self.y > self.ha):
                self.y = self.ha
            if ( self.y < 0):
                self.y = 0
            self.espace.coords("boule" ,self.x-self.rayon, self.y-self.rayon, self.x+self.rayon, self.y+self.rayon)
            self.root.after(self.duree, self.root.update())
     
        def Fenetre(self):
            # initialisation de la fenêtre contenant l'animation :
            self.mafenetre=Toplevel()
            self.mafenetre.title('Animation dans un canvas')
            self.flag_loop = 1
            self.mafenetre.protocol("WM_DELETE_WINDOW", self.detruire)
     
            self.la = 600
            self.ha = 300
            # position de la boule, initialisée au centre de l'écran
            self.x = self.la/2
            self.y = self.ha/2
     
            self.controle1 = Scale(self.mafenetre, from_ = 1, to = 200, label="Milli-sec", resolution = 1,
                                   tickinterval=50, orient=HORIZONTAL, length = self.la, command=self.ajuster)
            self.controle1.pack(side=BOTTOM, fill=X)
            self.controle2 = Scale(self.mafenetre, from_ = 10, to = 90, label="Déplacement", resolution = 1,
                                   tickinterval=20, orient=HORIZONTAL, length = self.la, command=self.ajuster)
            self.controle2.pack(side=BOTTOM, fill=X)
     
            self.espace = Canvas(self.mafenetre, bg="white", width=self.la, height=self.ha)
            self.espace.pack(side=TOP, fill=BOTH, expand=YES)
     
            self.laboule = self.espace.create_oval(self.x-self.rayon,self.y-self.rayon,
                                                   self.x+self.rayon,self.y+self.rayon, tag="boule", fill="green")
     
        def ajuster(self, event=None):
            self.duree = int(self.controle1.get())
            self.move = int(self.controle2.get())
     
        def detruire(self):
            # On detruit la TopLevel()...
            self.flag_loop = 0 # pour empêcher le dernier loop quand la TopLevel() est détruite
            self.mafenetre.destroy()
            sys.exit()
     
    # départ du programme principal :
    if __name__ == '__main__':
        app = Application()
    Je suppose que ce n'est pas la seule façon de faire ?

    Serait-il plus judicieux d'utiliser des threads ?
    Cela rendrait-il l'animation plus "souple" et plus "réactive", en monopolisant moins les ressources systèmes du à la boucle while infinie ?

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 26/12/2010, 21h20
  2. Utiliser une méthode non-static dans une méthode static
    Par mcfly37 dans le forum Débuter avec Java
    Réponses: 3
    Dernier message: 18/08/2010, 11h41
  3. Méthode de recherche dans une table de classes
    Par abir84 dans le forum Ruby
    Réponses: 8
    Dernier message: 05/10/2007, 13h58
  4. Utilisation des méthodes de classe dans une autre classe
    Par ChriGoLioNaDor dans le forum C++
    Réponses: 4
    Dernier message: 28/07/2007, 15h10
  5. Réponses: 5
    Dernier message: 01/02/2007, 13h14

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