Equation standard de la droite

Description

Ce petit programme illustre l'affichage d'une droite via sa forme standard. L'intérêt principal est d'avoir fait un Canvas modifiable, et une fonction qui retrace l'ensemble des axes et la droite en fonction de la taille (initiale ou modifiée) du Canvas, et en fonction de la variation des 3 paramètres suivants : le nombre de pixels d'une unité des axes et les coefficients a et b de l'équation de la droite sous sa forme y = a x + b. L'origine des axes est toujours bien centré dans le canvas, quel que soit sa forme et sa position. Le programme illustre aussi le fait QU'ON PEUT UTILISER pack et grid au sein d'une même application, pourvu qu'on respecte la condition de rester dans un GridManager au sein d'un conteneur donné (exemple de conteneur par excellence : Frame).

Source / Exemple :


# -*- coding:utf-8 -*-
from Tkinter import *

class Application:
    def __init__(self):
        self.root=Tk()
        self.root.title('Equation standard de la droite')

        self.root.geometry("600x400")

        self.barreEtat = Label(self.root, text="", bd=1, relief=SUNKEN, anchor=W)
        self.barreEtat.pack(side=BOTTOM, fill=X)

        # initialisation des trois variables principales :
        self.unite = 14.0 # pixels
        self.a = 1.0
        self.b = 1.0

        # Frame contenant les scales et utilisant Grid pour le positionnement de ses élements internes 
        self.c2 = Frame(self.root)
        self.c2.pack(side=RIGHT, fill=BOTH)

        label_unite = Label(self.c2, text="Unité")
        label_unite.grid(row=0, column=0)
        label_a = Label(self.c2, text="a")
        label_a.grid(row=0, column=1)
        label_b = Label(self.c2, text="b")
        label_b.grid(row=0, column=2)

        self.control_unite = Scale(self.c2, from_ = 10, to = 100, resolution = 1.0, orient = VERTICAL, length = 300, command = self.on_size_window)
        self.control_unite.set(self.unite)
        self.control_unite.grid(row=1, column=0)

        self.control_a = Scale(self.c2, from_ = -10, to = 10, resolution = 0.1, orient = VERTICAL, length = 300, command = self.on_size_window)
        self.control_a.set(self.a)
        self.control_a.grid(row=1, column=1)

        self.control_b = Scale(self.c2, from_ = -10, to = 10, resolution = 0.1, orient = VERTICAL, length = 300, command = self.on_size_window)
        self.control_b.set(self.b)
        self.control_b.grid(row=1, column=2)

        self.label_equat = Label(self.c2, text="y = ax + b")
        self.label_equat.grid(row=2, column=0, columnspan=3)
        equation_reelle = "y = "+str(self.a)+" x + "+str(self.b)
        self.label_equat2 = Label(self.c2, text=equation_reelle)
        self.label_equat2.grid(row=3, column=0, columnspan=3)

        la = 600
        ha = 400
        # nouvelles coordonnées de l'origine du graphe :
        self.x0 = la/2
        self.y0 = ha/2

        self.c = Canvas(self.root, bg="white", width=la, height=ha)
        self.c.pack(side=TOP, fill=BOTH, expand=YES)

        self.c.create_line(0, (ha/2), la, (ha/2), arrow=LAST, tag="axex")
        self.c.create_line((la/2), ha, (la/2), 0, arrow=LAST, tag="axey")

        # les deux points extrêmes pour tracer la droite :
        droite_x0 = -(la/2)/self.unite
        droite_y0 = self.equation(droite_x0)
        droite_x1 = (la/2)/self.unite
        droite_y1 = self.equation(droite_x1)
        self.c.create_line( self.crx(droite_x0), self.cry(droite_y0), self.crx(droite_x1), self.cry(droite_y1), fill="red", tag="droite")

        # les graduations sont gardées en mémoire !
        self.graduation_x_pos = []
        for i in range(1,21):
            z = self.c.create_line( self.x0 + i*self.unite, self.y0-4, self.x0 + i*self.unite, self.y0+4)
            self.graduation_x_pos.append(z)
             
        self.graduation_x_neg = []
        for i in range(1,21):
            z = self.c.create_line( self.x0 - i*self.unite, self.y0-4, self.x0 - i*self.unite, self.y0+4)
            self.graduation_x_neg.append(z)

        self.graduation_y_pos = []
        for i in range(1,21):
            z = self.c.create_line( self.x0-4, self.y0 + i*self.unite, self.x0+4, self.y0 + i*self.unite)
            self.graduation_y_pos.append(z)

        self.graduation_y_neg = []
        for i in range(1,21):
            z = self.c.create_line( self.x0-4, self.y0 - i*self.unite, self.x0+4, self.y0 - i*self.unite)
            self.graduation_y_neg.append(z)

        self.root.bind("<Configure>", self.on_size_window)

        self.root.mainloop()

    def on_size_window(self, event=None):
        # on récupère les nouvelles tailles du canvas :
        la = self.c.winfo_width()
        ha = self.c.winfo_height()
        # on récupère la nouvelle origine :
        self.x0 = la/2
        self.y0 = ha/2
        # on indique ces dimensions dans la barre d'état :
        taille = " Canvas :  larg. = "+str(la)+"     haut. = "+str(ha)
        self.barreEtat.config(text=taille)

        self.unite = float(self.control_unite.get())
        self.a = float(self.control_a.get())
        self.b = float(self.control_b.get())

        # on replace les deux axes :
        self.c.coords("axex", 0, (ha/2), la, (ha/2))
        self.c.coords("axey", (la/2), ha, (la/2), 0)

        # on replace les graduations depuis la nouvelle origine :
        j = 1
        for z in self.graduation_x_pos:
            self.c.coords( z, self.x0 + j*self.unite, self.y0-4, self.x0 + j*self.unite, self.y0+4)
            j = j + 1
        j = 1
        for z in self.graduation_x_neg:
            self.c.coords( z, self.x0 - j*self.unite, self.y0-4, self.x0 - j*self.unite, self.y0+4)
            j = j + 1
        j = 1
        for z in self.graduation_y_pos:
            self.c.coords( z, self.x0-4, self.y0 + j*self.unite, self.x0+4, self.y0 + j*self.unite)
            j = j + 1
        j = 1
        for z in self.graduation_y_neg:
            self.c.coords( z, self.x0-4, self.y0 - j*self.unite, self.x0+4, self.y0 - j*self.unite)
            j = j + 1

        # les deux points extrêmes pour tracer la droite :
        droite_x0 = -(la/2)/self.unite
        droite_y0 = self.equation(droite_x0)
        droite_x1 = (la/2)/self.unite
        droite_y1 = self.equation(droite_x1)
        self.c.coords("droite", self.crx(droite_x0), self.cry(droite_y0), self.crx(droite_x1), self.cry(droite_y1))

        if (self.a != 0.0):
            premiere_partie = str(self.a)+" x "
        else:
            premiere_partie = ""

        if (self.b < 0):
            seconde_partie = "- "+str(abs(self.b))
        elif (self.b == 0.0):
            seconde_partie = ""
        else:
            seconde_partie = "+ "+str(self.b)

        if (self.a==0.0) and (self.b==0.0):
            premiere_partie = "0"

        equation_reelle = "y = "+premiere_partie+seconde_partie
        self.label_equat2.config(text=equation_reelle)

    def equation(self, coord_x):
        # donne le résultat y de la fonction de la droite affichée
        return ((coord_x * self.a) + self.b)

    def crx(self, coord_x):
        # cette fonction transforme une coordonnée unitaire en un réel positionnement
        # en pixels sur l'écran
        return self.x0 + coord_x * self.unite

    def cry(self, coord_y):
        # cette fonction transforme une coordonnée unitaire en un réel positionnement
        # en pixels sur l'écran
        # les Y d'un canvas étant positif en allant vers le bas, il a fallu faire un -
        # pour faire fonctionner l'axe des Y avec les positifs vers le haut !
        return self.y0 - coord_y * self.unite
        

# départ du programme principal :
if __name__ == '__main__':
    app = Application()

Conclusion :


J'espère que ce petit bout de code servira à d'autres débutants, et à appréhender notamment les GridManager Pack et Grid...

Codes Sources

A voir également

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.