Illustration de sinus et de cosinus

Soyez le premier à donner votre avis sur cette source.

Vue 8 748 fois - Téléchargée 691 fois

Description

Un programme simple qui permet d'illustrer dynamiquement les fonctions sinus et cosinus. Ecrit pour Python 2.6, l'interface graphique fait appel à Tkinter. Pas de difficulté majeure si ce n'est la structuration du code en classe. Une particularité : c'est l'utilisation d'une variable de classe self.u, qui contient une valeur entière en pixels, sur laquelle se basent toutes les dimensions proportionnelles de l'application. En d'autres termes, tapez 12 dans cette valeur pour avoir une petite taille de la fenêtre (et les canvas qu'elle contient), tapez 24, et l'interface doublera de taille...

Source / Exemple :


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

# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# Illustration du SINUS et du COSINUS
# -----------------------------------------------------------------------------
# Auteur : Calogero GIGANTE
# Version python : 2.6.4. avec Tkinter
# Objectif : illustrer dynamiquement le sin et le cos d'un angle en degrés.
# Date : 17 janvier 2010
# Site web : www.gigante.be
# Site python : www.gigante.be/python
# License : GPL
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------

from Tkinter import *
import tkMessageBox
from math import *

class Application:
    def __init__(self):
        self.root=Tk()
        self.root.title('Sinus et cosinus - par C. Gigante')

        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)
        bouton_apropos = Button(self.c4, text="A propos de ce programme...", command=self.afficherapropos)
        bouton_apropos.pack(side=RIGHT)

        self.root.mainloop()

    def redessinertout(self, event=None):
        angle = int(self.controle.get())
        nouv_sin = sin(radians(angle))
        nouv_cos = cos(radians(angle))

        # update de l'arc symbolisant l'angle dans le canvas 1
        arc_angle = angle
        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)

    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"+
            "Auteur : Calogero GIGANTE - www.gigante.be - 2010")

# départ du programme principal :

f = Application()

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

Messages postés
28
Date d'inscription
jeudi 10 juillet 2003
Statut
Membre
Dernière intervention
25 octobre 2009

Merci.
Messages postés
382
Date d'inscription
mercredi 23 août 2006
Statut
Membre
Dernière intervention
8 novembre 2010
11
Maque la note, c'est fait
Messages postés
382
Date d'inscription
mercredi 23 août 2006
Statut
Membre
Dernière intervention
8 novembre 2010
11
Beau boulot rien à redire de particulier ça vaut bien un 8/10
Messages postés
12
Date d'inscription
mercredi 16 juin 2004
Statut
Membre
Dernière intervention
3 mai 2010

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
Messages postés
28
Date d'inscription
jeudi 10 juillet 2003
Statut
Membre
Dernière intervention
25 octobre 2009

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 ?
Afficher les 9 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.