ILLUSTRATION DE SINUS ET DE COSINUS

bothan Messages postés 12 Date d'inscription mercredi 16 juin 2004 Statut Membre Dernière intervention 3 mai 2010 - 27 janv. 2010 à 13:17
cs_calogerogigante Messages postés 28 Date d'inscription jeudi 10 juillet 2003 Statut Membre Dernière intervention 25 octobre 2009 - 29 juil. 2010 à 22:26
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/51135-illustration-de-sinus-et-de-cosinus

cs_calogerogigante Messages postés 28 Date d'inscription jeudi 10 juillet 2003 Statut Membre Dernière intervention 25 octobre 2009
29 juil. 2010 à 22:26
Merci.
aera group Messages postés 382 Date d'inscription mercredi 23 août 2006 Statut Membre Dernière intervention 8 novembre 2010 18
28 juil. 2010 à 14:46
Maque la note, c'est fait
aera group Messages postés 382 Date d'inscription mercredi 23 août 2006 Statut Membre Dernière intervention 8 novembre 2010 18
28 juil. 2010 à 14:46
Beau boulot rien à redire de particulier ça vaut bien un 8/10
bothan Messages postés 12 Date d'inscription mercredi 16 juin 2004 Statut Membre Dernière intervention 3 mai 2010
29 janv. 2010 à 09:40
Salut calogerogigante

En effet même sans gestion des thread ton programme fonctionne, peut être parce qu'il n'y en a qu'un.

N'étant pas du tout un spécialiste de python et encore moins des threads en python, je ne saurais te dire si ma gestion des threads est correcte.

Cela dit un certain nombre d'ouvrages dont celui de G.Swinnen que tu trouveras ici http://www.inforef.be/swi/download/python_notes.pdf font le point et te seront de meilleur conseil que moi.

Bonne continuation
cs_calogerogigante Messages postés 28 Date d'inscription jeudi 10 juillet 2003 Statut Membre Dernière intervention 25 octobre 2009
28 janv. 2010 à 13:34
Petite question BUTHON : es-tu sûr d'utiliser les threads correctement ? Car je viens de tester ton programme et mon code simplifié ci-dessus sans invoquer la classe Thread, eh bien, ça marche aussi...

Exemple :

#!/usr/local/bin/python
# -*- coding:utf-8 -*-
from Tkinter import *
import threading
from time import *
import sys

class Application:
def __init__(self):
self.Terminated = False
self.root=Tk()
self.root.title('Barre qui avance avec un thread...')
self.root.geometry('600x160')
self.root.protocol("WM_DELETE_WINDOW", self.finirapplication)

self.valeur = 1

self.c1 = Canvas(self.root, bg="white")
self.c1.pack(side=LEFT, expand=YES, fill=BOTH)

self.barre = self.c1.create_rectangle( 10, 50, 11, 100, fill="yellow")

#Boutons du 4éme canvas :
bouton_animate = Button(self.root, text="Démarrer", command=self.ianimate)
bouton_stop = Button(self.root, text="Arrêt", command=self.stop)
bouton_reprendre = Button(self.root, text="Reprendre", command=self.reprendre)
bouton_reset = Button(self.root, text="Remise à zéro", command=self.reset)
bouton_animate.pack(side=TOP, expand=YES)
bouton_stop.pack(side=TOP, expand=YES)
bouton_reprendre.pack(side=TOP, expand=YES)
bouton_reset.pack(side=TOP, expand=YES)

self.root.mainloop()

def stop(self):
#Thread Stop :
self.Terminated = True

def redessiner(self,x):
#Mise a jour de la barre :
self.valeur = x

self.c1.coords(self.barre, 10, 50, 10+x, 100)

def redessinertout(self, event=None):
#Mise a jour de la barre avec la valeur donnée par self.valeur :
self.redessiner(self.valeur)

def reset(self, event=None):
if self.Terminated == False:
self.Terminated = True
self.redessiner(1)

def reprendre(self):
#Reprise de l'animation :
self.animate()

def ianimate(self):
#Lancement animation 0-500 :
self.valeur = 0
self.animate()

def animate(self):
#Lancement de l'animation
if self.Terminated == True:
self.Terminated = False

while not self.Terminated:
for i in range(500):
if self.Terminated == True:
return
if i >= self.valeur:
self.valeur = i
sleep(0.01)
self.redessiner(i)
self.root.update()
#update du controle
self.valeur = 0

def finirapplication(self):
self.Terminated = True
self.stop()
sys.exit()

# Lancement programme principal :
if __name__ == "__main__":
app = Application()

Un thread t ne doit-il pas faire appel à la méthode t.run() à un moment donné de son existence ?
cs_calogerogigante Messages postés 28 Date d'inscription jeudi 10 juillet 2003 Statut Membre Dernière intervention 25 octobre 2009
28 janv. 2010 à 11:55
Salut BOTHAN, merci pour ta correction, il n'y a plus un seul message d'erreur maintenant. Je suis content de ton code car il m'a fourni un superbe exemple simple d'utilisation des Threads avec un graphisme dans le Canvas. J'ai fait un petit travail de simplification de code, pour aller à l'essentiel et comprendre comment fonctionne la manipulation d'une fonction avec un Thread, en m'inspirant à 100% de ton code modifié.

Voici ce que cela donne :

#!/usr/local/bin/python
# -*- coding:utf-8 -*-
from Tkinter import *
import threading
from time import *
import sys

class Application(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.Terminated = False
self.root=Tk()
self.root.title('Barre qui avance avec un thread...')
self.root.geometry('600x160')
self.root.protocol("WM_DELETE_WINDOW", self.finirapplication)

self.valeur = 1

self.c1 = Canvas(self.root, bg="white")
self.c1.pack(side=LEFT, expand=YES, fill=BOTH)

self.barre = self.c1.create_rectangle( 10, 50, 510, 100, fill="yellow")

#Boutons du 4éme canvas :
bouton_animate = Button(self.root, text="Démarrer", command=self.ianimate)
bouton_stop = Button(self.root, text="Arrêt", command=self.stop)
bouton_reprendre = Button(self.root, text="Reprendre", command=self.reprendre)
bouton_reset = Button(self.root, text="Remise à zéro", command=self.reset)
bouton_animate.pack(side=TOP, expand=YES)
bouton_stop.pack(side=TOP, expand=YES)
bouton_reprendre.pack(side=TOP, expand=YES)
bouton_reset.pack(side=TOP, expand=YES)

self.root.mainloop()

def stop(self):
#Thread Stop :
self.Terminated = True

def redessiner(self,x):
#Mise a jour de la barre :
self.valeur = x

self.c1.coords(self.barre, 10, 50, 10+x, 100)

def redessinertout(self, event=None):
#Mise a jour de la barre avec la valeur donnée par self.valeur :
self.redessiner(self.valeur)

def reset(self, event=None):
if self.Terminated == False:
self.Terminated = True
self.redessiner(1)

def reprendre(self):
#Reprise de l'animation :
self.animate()

def ianimate(self):
#Lancement animation 0-500 :
self.valeur = 0
self.animate()

def animate(self):
#Lancement de l'animation
if self.Terminated == True:
self.Terminated = False

while not self.Terminated:
for i in range(500):
if self.Terminated == True:
return
if i >= self.valeur:
self.valeur = i
sleep(0.01)
self.redessiner(i)
self.root.update()
#update du controle
self.valeur = 0

def finirapplication(self):
self.Terminated = True
self.stop()
sys.exit()

# Lancement programme principal :
if __name__ == "__main__": app Application()

Est-ce que c'est correct, ce que j'ai fait ?

Comment créer un canvas maintenant qui possède plusieurs barres jaunes, chacune manipulées par un thread différent ?
bothan Messages postés 12 Date d'inscription mercredi 16 juin 2004 Statut Membre Dernière intervention 3 mai 2010
27 janv. 2010 à 19:42
Salut

stop n'est pas reconnue comme methode et du coup on sort de la boucle et ça m'arrange bien d'ailleurs.

ligne229: mettre un return a la place de stop qui permet de sortir de la boucle de maniere plus correcte

en même temps on peut aussi retirer le 2eme parametre de animate que je n'utilise pas

Bonne soirée
cs_calogerogigante Messages postés 28 Date d'inscription jeudi 10 juillet 2003 Statut Membre Dernière intervention 25 octobre 2009
27 janv. 2010 à 14:44
Waaaouuuuwwww !!!!

Mille mercis Bothan pour ton ajout qui me ravit, pourquoi ?

Parce que je n'ai pas encore commencé l'étude des threads qui m'intimident un peu...

Ton exemple est donc une superbe opportunité d'approcher le fonctionnement de ces bestioles-là... sur mon propre programme !!! Trop fun !

Juste une petite question : ton code s'exécute très bien sur mon PC, mais j'ai des messages d'erreurs sur la console quand je stoppe ou quand je reprends l'animation...

global name stop is not defined

C'est normal ?
bothan Messages postés 12 Date d'inscription mercredi 16 juin 2004 Statut Membre Dernière intervention 3 mai 2010
27 janv. 2010 à 13:17
Bonjour

Bravo pour ce petit code educatif que je me suis permis de completer pour utiliser tes routines de mise a jour des canvas afin de transformer l'application en une animation interactive: en voici le code modifié si cela t'interesse.

#!/usr/local/bin/python
# -*- coding:utf-8 -*-

# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# Illustration dynamique des fonctions Sin(x) et Cos(x)
# -----------------------------------------------------------------------------
# Auteurs : Calogero GIGANTE - MRG
# Version python : 2.6.4. avec Tkinter
# Objectif : illustrer dynamiquement le sinus et le cosinus d'un angle en degrés.
# Date : 27 janvier 2010
# Site web : www.gigante.be
# Site python : www.gigante.be/python
# License : GPL
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------

from Tkinter import *
import tkMessageBox
import threading
from math import *
from time import *

class Application(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.Terminated = False
self.root=Tk()
self.root.title('Sinus et cosinus - par C. Gigante - Mod MRG')
self.root.geometry('740x720+300+50')

self.u = 24 # unite en px servant à dimensionner TOUS les composants graphiques
self.trait = 2 # épaisseur en px des barres cos et sin

# création des 4 canvas :
self.c1 = Canvas(self.root, bg="white", width=12*self.u, height=12*self.u)
self.c1.grid(row=0, column=0, padx=0, pady=0)
self.c2 = Canvas(self.root, bg="white", width=17*self.u, height=12*self.u)
self.c2.grid(row=0, column=1, padx=0, pady=0)
self.c3 = Canvas(self.root, bg="white", width=12*self.u, height=17*self.u)
self.c3.grid(row=1, column=0, padx=0, pady=0)
self.c4 = Canvas(self.root, width=17*self.u, height=17*self.u)
self.c4.grid(row=1, column=1, padx=0, pady=0)

self.nbre_de_pixels_sur_axe_x = self.u * 12
# sur ce nombre de pixels, s'étendent 360 degrés.
self.nbre_pixels_pour_1_deg = float(self.nbre_de_pixels_sur_axe_x)/360

coordspoursin = []
for t in range(0,self.nbre_de_pixels_sur_axe_x,1):
x = t
y = sin ( radians( x / self.nbre_pixels_pour_1_deg ))
xx = 2 * self.u + x
yy = 6 * self.u - (4 * self.u) * y
coordspoursin.append((xx, yy))

coordspourcos = []
# attention, ici, on a tenu compte de l'orientation vers le bas du tracé
# de la fonction cosinus
for t in range(0,self.nbre_de_pixels_sur_axe_x,1):
y = t
x = cos ( radians( y / self.nbre_pixels_pour_1_deg ))
yy = 2 * self.u + y
xx = 6 * self.u + (4 * self.u) * x
coordspourcos.append((xx, yy))

# dessins des éléments fixes du 1er canvas :
self.c1.create_line( 6 * self.u, 11 * self.u, 6 * self.u, 1 * self.u, arrow=LAST, tag="c1_axex")
self.c1.create_line( 1 * self.u, 6 * self.u, 11 * self.u, 6 * self.u, arrow=LAST, tag="c1_axey")
self.c1.create_oval( 2 * self.u, 2 * self.u, 10 * self.u, 10 * self.u)
self.c1.create_text( 7 * self.u, 1 * self.u, text="1")
self.c1.create_text( 11 * self.u, 5 * self.u, text="1")
self.c1.create_text( 1 * self.u, 5 * self.u, text="-1")
self.c1.create_text( 5 * self.u, 11 * self.u, text="-1")
self.c1_x0 = 6 * self.u
self.c1_y0 = 6 * self.u
# dessins des éléments mobiles du 1er canvas : self.arc1 self.c1.create_arc( 5 * self.u, 5 * self.u, 7 * self.u, 7 * self.u, start 0, extent = 0, fill="", style=ARC, outline="#EFEFEF", width = 1, tag="arc1")
self.barrecosc1 = self.c1.create_line( self.c1_x0, self.c1_y0 - (self.trait/2), 10 * self.u, 6 * self.u - (self.trait/2), fill="green", width=self.trait, tag="barrecosc1")
# le (- self.trait/2) de self.barrecosc1 sert à décaler légèrement la vue de la barre cosinus de l'axe horizontal
self.barresinc1 = self.c1.create_line( 10 * self.u, 6 * self.u, 10 * self.u, 6 * self.u, fill="red", width=self.trait, tag="barresinc1")
self.rayon = self.c1.create_line( self.c1_x0, self.c1_y0, 10 * self.u, 6 * self.u, tag="rayon")
self.boule1 = self.c1.create_oval( 9.8 * self.u, 5.8 * self.u, 10.2 * self.u, 6.2 * self.u, fill="orange", width=0, tag="boule1")

# dessins des éléments fixes du 2ème canvas :
self.c2.create_line( 1 * self.u, 6 * self.u, 16 * self.u, 6 * self.u, arrow=LAST, tag="c2_axex")
self.c2.create_line( 2 * self.u, 11 * self.u, 2 * self.u, 1 * self.u, arrow=LAST, tag="c2_axey")
self.c2.create_line( 5 * self.u, 5.5 * self.u, 5 * self.u, 6.5 * self.u) # trait x
self.c2.create_line( 8 * self.u, 5.5 * self.u, 8 * self.u, 6.5 * self.u) # trait x
self.c2.create_line( 11 * self.u, 5.5 * self.u, 11 * self.u, 6.5 * self.u) # trait x
self.c2.create_line( 14 * self.u, 5.5 * self.u, 14 * self.u, 6.5 * self.u) # trait x
self.c2.create_line( 1.5 * self.u, 2 * self.u, 2.5 * self.u, 2 * self.u) # trait y
self.c2.create_line( 1.5 * self.u, 10 * self.u, 2.5 * self.u, 10 * self.u) # trait y
self.c2.create_text( 1 * self.u, 2 * self.u, text="1")
self.c2.create_text( 1 * self.u, 10 * self.u, text="-1")
self.c2.create_text( 3 * self.u, 1 * self.u, text="Sin(x)")
self.c2.create_text( 15 * self.u, 5 * self.u, text="x (degré)")
self.c2.create_line( coordspoursin, fill="blue", smooth=1 )
self.c2_x0 = 2 * self.u
self.c2_y0 = 6 * self.u
# dessins des éléments mobiles du 2ème canvas :
self.barresinc2 = self.c2.create_line( 2 * self.u, 6 * self.u, 2 * self.u, 6 * self.u, fill="red", width=self.trait, tag="barresinc2")
self.boule2 = self.c2.create_oval( 1.8 * self.u, 5.8 * self.u, 2.2 * self.u, 6.2 * self.u, fill="orange", width=0, tag="boule2")

# dessins des éléments fixes du 3ème canvas :
self.c3.create_line( 6 * self.u, 1 * self.u, 6 * self.u, 16 * self.u, arrow=LAST, tag="c3_axex")
self.c3.create_line( 1 * self.u, 2 * self.u, 11 * self.u, 2 * self.u, arrow=LAST, tag="c3_axey")
self.c3.create_line( 2 * self.u, 1.5 * self.u, 2 * self.u, 2.5 * self.u) # trait y
self.c3.create_line( 10 * self.u, 1.5 * self.u, 10 * self.u, 2.5 * self.u) # trait y
self.c3.create_line( 5.5 * self.u, 5 * self.u, 6.5 * self.u, 5 * self.u) # trait x
self.c3.create_line( 5.5 * self.u, 8 * self.u, 6.5 * self.u, 8 * self.u) # trait x
self.c3.create_line( 5.5 * self.u, 11 * self.u, 6.5 * self.u, 11 * self.u) # trait x
self.c3.create_line( 5.5 * self.u, 14 * self.u, 6.5 * self.u, 14 * self.u) # trait x
self.c3.create_text( 2 * self.u, 1 * self.u, text="-1")
self.c3.create_text( 10 * self.u, 1 * self.u, text="1")
self.c3.create_text( 7 * self.u, 1 * self.u, text="Cos(x)")
self.c3.create_text( 8 * self.u, 16 * self.u, text="x (degré)")
self.c3.create_line( coordspourcos, fill="blue", smooth=1 )
self.c3_x0 = 6 * self.u
self.c3_y0 = 2 * self.u
# dessins des éléments mobiles du 3ème canvas :
self.barrecosc3 = self.c3.create_line( self.c3_x0, self.c3_y0, self.c3_x0 + 4 * self.u, self.c3_y0, fill="green", width=self.trait, tag="barrecosc3")
self.boule3 = self.c3.create_oval( 9.8 * self.u, 1.8 * self.u, 10.2 * self.u, 2.2 * self.u, fill="orange", width=0, tag="boule3")

# éléments du 4ème canvas : imgsin PhotoImage(file "img_sinus.gif") imgcos PhotoImage(file "img_cosinus.gif")
img1 = Label(self.c4, image=imgsin)
img1.pack(side=TOP) self.controle Scale(self.c4, from_ 0, to = 360, label="Degrés", resolution = 1, tickinterval=45, orient=HORIZONTAL, length = 15*self.u, command = self.redessinertout)
self.controle.pack(side=TOP)
img2 = Label(self.c4, image=imgcos)
img2.pack(side=TOP)

#Spacers pour les boutons du 4éme canvas ::
spcr = Label(self.c4, text=" ")
spcr2 = Label(self.c4, text=" ")
spcr3 = Label(self.c4, text=" ")

#Boutons du 4éme canvas :
bouton_animate = Button(self.c4, text="Animation 0-360", command=self.ianimate)
bouton_stop = Button(self.c4, text="Arret", command=self.stop)
bouton_reprendre =Button(self.c4, text="Reprendre", command=self.reprendre)
bouton_reset = Button(self.c4, text="Remise a 0", command=self.reset)
bouton_apropos = Button(self.c4, text="A propos...", command=self.afficherapropos)
bouton_animate.pack(side=LEFT)
spcr.pack(side=LEFT)
bouton_stop.pack(side=LEFT)
spcr2.pack(side=LEFT)
bouton_reprendre.pack(side=LEFT)
spcr3.pack(side=LEFT)
bouton_reset.pack(side=LEFT)
bouton_apropos.pack(side=RIGHT)
self.root.mainloop()

#Thread Stop :
def stop(self):
self.Terminated = True

#Mise a jour des canvas avec un angle donné :
def redessiner(self,x):

self.controle.set(x)
angle = int(self.controle.get())
nouv_sin = sin(radians(x))
nouv_cos = cos(radians(x))

# update de l'arc symbolisant l'angle dans le canvas 1
arc_angle = x
if arc_angle == 360:
arc_angle = 359 # ceci est fait pour éviter la disparition de l'arc quand l'angle atteint 360 deg.
self.c1.itemconfigure("arc1",extent=arc_angle)

# update de la boule 1 (et du rayon) :
x = self.c1_x0 + nouv_cos * 4 * self.u
y = self.c1_y0 - nouv_sin * 4 * self.u
self.c1.coords("rayon", self.c1_x0, self.c1_y0, x, y) # update du rayon
self.c1.coords("boule1", x - 0.2 * self.u, y - 0.2 * self.u, x + 0.2 * self.u, y + 0.2 * self.u)

# update de la barre du sin dans le canvas 1
dx = self.c1_x0 + nouv_cos * 4 * self.u
dy = self.c1_y0 - nouv_sin * 4 * self.u
self.c1.coords("barresinc1", dx, 6 * self.u, dx, dy)

# update de la barre du cos dans le canvas 1
self.c1.coords("barrecosc1", self.c1_x0 , self.c1_y0 - (self.trait/2) , self.c1_x0 + nouv_cos * 4 * self.u, self.c1_y0 - (self.trait/2) )

# update de la barre du sin dans le canvas 2
dx2 = self.c2_x0 + angle * self.nbre_pixels_pour_1_deg
dy2 = self.c2_y0 - nouv_sin * 4 * self.u
self.c2.coords("barresinc2", dx2, 6 * self.u, dx2, dy2)
# update de la boule 2 dans le canvas 2
self.c2.coords("boule2", dx2 - 0.2 * self.u, dy2 - 0.2 * self.u, dx2 + 0.2 * self.u, dy2 + 0.2 * self.u)

# update de la barre du cos dans le canvas 3
dx3 = self.c3_x0 + nouv_cos * 4 * self.u
dy3 = self.c3_y0 + angle * self.nbre_pixels_pour_1_deg
self.c3.coords("barrecosc3", self.c3_x0, dy3, dx3, dy3)
# update de la boule 3 dans le canvas 3
self.c3.coords("boule3", dx3 - 0.2 * self.u, dy3 - 0.2 * self.u, dx3 + 0.2 * self.u, dy3 + 0.2 * self.u)

#Mise a jour des canvas avec un angle donné par le controle :
def redessinertout(self, event=None):
angle = int(self.controle.get())
self.redessiner(angle)

def reset(self, event=None):
if self.Terminated == False:
self.Terminated = True
self.redessiner(0)

#Reprise de l'animation :
def reprendre(self):
self.animate(self.controle.get())

#Lancement animation 0-360 :
def ianimate(self):
self.controle.set(0)
self.animate(0)

#Lancement de l'animation
def animate(self, y):
if self.Terminated == True:
self.Terminated = False

while not self.Terminated:
for i in range(361):
if self.Terminated == True:
stop
if i >= int(self.controle.get()):
self.controle.set(i)
sleep(0.02)
self.redessiner(i)
self.root.update()

# update de la boule 2 dans le canvas 2
dx2 = self.c2_x0 + 0 * self.nbre_pixels_pour_1_deg
dy2 = self.c2_y0 - sin(radians(0)) * 4 * self.u
self.c2.coords("boule2", dx2 - 0.2 * self.u, dy2 - 0.2 * self.u, dx2 + 0.2 * self.u, dy2 + 0.2 * self.u)

# update de la boule 3 et barre 3 dans le canvas 3
dx3 = self.c3_x0 + cos(radians(0)) * 4 * self.u
dy3 = self.c3_y0 + 0 * self.nbre_pixels_pour_1_deg
self.c3.coords("boule3", dx3 - 0.2 * self.u, dy3 - 0.2 * self.u, dx3 + 0.2 * self.u, dy3 + 0.2 * self.u)
self.c3.coords("barrecosc3", self.c3_x0, dy3, dx3, dy3)

#update du controle
self.controle.set(0)

#Affichage MsgBox :
def afficherapropos(self):
tkMessageBox.showinfo(
"A propos de...",
"Sinus et Cosinus\n\n"+
"Un petit programme écrit en Python 2.6 qui\n"+
"utilise Tkinter et qui permet simplement\n"+
"de visualiser dynamiquement le sinus\n"+
"et le cosinus d'un angle en degrés.\n\n"+
"Auteurs : Calogero GIGANTE - MRG - www.gigante.be - 2010")

# Lancement programme principal :
f = Application()

Pour l'indentation cela a l'air OK.

Bonne continuation
Rejoignez-nous