Projet

Général

Profil

Le code Python de l'interface » interface.py

Clémence Tilhet, 07/07/2021 17:05

 
#importation des librairies
import math
import serial
import time
import sys

import numpy as np

import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
import matplotlib.animation as animation
from matplotlib import style

from tkinter import *
from tkinter.filedialog import askopenfilename
import tkinter as tk






#définition de la police
LARGE_FONT=("Verdana",16)
#on détermine le style du graphique (avec fond gris)
style.use("ggplot")



##### ESSAI FIGURE EN TEMPS RÉEL #####

# #on définit la taille de la figure
# f = Figure(figsize = (5,5), dpi = 100)
# #ajout de la figure avec subplot (111 = figure 1 par 1 et figure numéro 1)
# a = f.add_subplot(111)
# #on renseignes les données
#
#
# def animate(i):
# pullData = open("data","r").read()
# dataList = pullData.split('\n')
# xList = []
# for eachLine in dataList:
# if len(eachLine) >1:
# x=eachLine
# xList.append(int(x))
# a.clear()
# a.plot(xList)



#Création de la classe Graphique
class Graphique(tk.Tk):


#initialisateur appelé automatiquement après qu'un objet ait été créé
#on donne l'état de départ
#accepet des paramètres, self doit être le premier paramètre
#self = l'objet cible, c'est une variable qui contient une référence vers l'objet en cours de création
def __init__(self, *args, **kwargs):


#on initalise la fenêtre
tk.Tk.__init__(self, *args, **kwargs)
# défintion du titre
tk.Tk.wm_title(self, "Graphique")

container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0,weight=1)
container.grid_columnconfigure(0,weight=1)

self.frames = {}

for F in (StartPage, PageOne, PageTwo, PageThree):
frame = F(container,self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)

def show_frame(self,cont):
frame = self.frames[cont]
frame.tkraise()


#page d'accueil
class StartPage(tk.Frame):

def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
#inscription
label = tk.Label(self,text="Bienvenue", font=LARGE_FONT)
#placement du label à la ligne 2, colonne 6
label.grid(row = 2, column=6)
#on créé un bouton qui va permettre de rediriger vers l'affichage de la température sur une autre page
button = tk.Button(self, text = "Afficher la température", command = lambda: controller.show_frame(PageOne))
#Placement du bouton
button.grid(row = 3, column = 6)
#bouton qui redirige vers la page de control des Leds
button2 = tk.Button(self, text = "Contrôler les LEDs", command=lambda: controller.show_frame(PageTwo))
#placement du bouton
button2.grid(row=4, column = 6)
#bouton qui redirige vers la page d'un formulairre
button3 = tk.Button(self, text = "Remplir un formulaire", command=lambda: controller.show_frame(PageThree))
button3.grid(row=5, column = 6)
#en haut, on place un menu
zoneMenu = Frame(self, borderwidth=3, bg='#557788')
zoneMenu.grid(row=0, column = 0)
#on créé chaque onglet du menu :

# Création de l'onglet Fichier
menuFichier = Menubutton(zoneMenu, text = 'Fichier', width='20', borderwidth=2, bg='gray', activebackground='darkorange', relief = RAISED)
menuFichier.grid(row=0, column=0)

# Création de l'onglet Edition
menuEdit = Menubutton(zoneMenu, text='Editer', width='20', borderwidth=2, bg='gray', activebackground='darkorange',relief = RAISED)
menuEdit.grid(row=0,column=1)

# Création de l'onglet Format
menuFormat = Menubutton(zoneMenu, text='Format', width='20', borderwidth=2, bg='gray', activebackground='darkorange',relief = RAISED)
menuFormat.grid(row=0,column=2)

menuAffichage = Menubutton(zoneMenu, text='Affichage', width='20', borderwidth=2, bg='gray', activebackground='darkorange',relief = RAISED)
menuAffichage.grid(row=0,column=3)


#création des fonctions servant aux différents onglets
# fonctions de l'onglet Affichage, elles changent juste la couleur du fonc
def fondClair():
self.configure(bg = 'pink')

def fondSombre():
self.configure(bg= 'black')

# création d'un menu déroulant
Menu(menuAffichage,tearoff=0)
menuDeroulant1 = Menu(menuAffichage)
menuDeroulant1.add_command(label='Fond clair', command = fondClair)
menuDeroulant1.add_command(label='Fond sombre', command = fondSombre)

# attribution du menu déroulant au menu menuAffichage
menuAffichage.configure(menu=menuDeroulant1)




#fonctions de l'onglet Fichier
#on peut ouvrir un fichier, afficher un message

#on ouvre un fichier de l'ordinateur
def openFile():
file = askopenfilename(title="Choisir un fichier à ouvrir",filetypes=[("PNG image", ".png"), ("GIF image", ".gif"), ("All files", ".*")])
print( file )

#cette fonction afficher seulement "Menu Clicked" sur le terminal
def doSomething(fenetre):
print("Menu clicked")

#cette fonction affiche un message sur l'interface
#il est seulement marqué ce qu'ily a entre parenthèses
def doAbout(fenetre):
messagebox.showinfo("My title", "My message")
#
#affichage du menu Fichier
Menu(menuFichier, tearoff=0)
menuDeroulant2=Menu(menuFichier)
#on détaille chaque possibilité de l'onglet Fichier
#chaque possibilité est reliée à une fonction
menuDeroulant2.add_command(label="New", command= doSomething)
menuDeroulant2.add_command(label="Open", command= openFile)
menuDeroulant2.add_command(label="Save", command= doSomething)
menuDeroulant2.add_separator()
menuDeroulant2.add_command(label="Exit", command=self.quit)

menuFichier.configure(menu=menuDeroulant2)


#Deuxième page de l'interface qui va permettre d'afficher la température
class PageOne(tk.Frame) :
#fonction d'initialisation
def __init__(self,parent,controller):
tk.Frame.__init__(self,parent)
#on affiche un label
label = tk.Label(self, text="Graphe de la température", font=LARGE_FONT)
label.pack(pady=10, padx=10)


# res=entree1.get()
# print(res)
#fonction de controle qui va permettre d'actionner la prise de température et son affichage
def control():
#on précise le port, ici l'arduino est /dev/ttyACM0
ser = serial.Serial('/dev/ttyACM0',9600);
print(ser)

#Réception et stockage des données
#on prend ici en compte données

#cette fonction se déclenche lorsque l'on appuie sur le bouton Actionner
def getEntry():
#On récupère le texte entré par l'utilisateur afin de savoir combien de points il veut sur sa courbe
res = entree1.get()
print(res)

#on initialise un tableau dans lequel les données vont arriver
rawdata =[]
compt = 0;

#on remplit le tableau avec les valeurs du fichier texte
#on prend on considérations les n valeurs, n étant le nombre décidé par l'utilisateur
while (compt<int(res)):
#on rremplit le tableau rawdata par les valeurs du fichier texte
rawdata.append(str(ser.readline()))
#on rajoute 1 au compteur jusqu'a ce qu'il atteigne res (la valeur décidée par l'utilisateur)
compt+=1
#on affiche le tableau rawdata sur le terminal
print(rawdata);

#les valeurs sur le terminal s'affiche de cette manière :
#["b'val1\\n'", "b'val2\\n'", "b'val\\n'"]
#On veut un tableau plus clair, sans le b ni le \\n
#Pour cela, on écrit la fonction nettoie qui va permettre d'afficher un tableau :['val1', 'val2', 'val3']
def nettoie(L):
#on initialise un nouveau tableau
newL=[]
#jusqu'a ce qu'on atteigne la fin de la longueur de notre tableau rawdata
for i in range(len(L)):
#on réduit le b et le \\n
temp=L[i][2:]
#on remplit le nouveau tableau newL avec la valeur "nettoyée"
newL.append(temp[:-5])
#on retourne le nouveau tableau
return newL

#on appelle la fonction nettoie
cleandata=nettoie(rawdata)
#on écrit le nouveau tableau dans le terminal
print(cleandata)

#on veut maintenant remplir le fichier texte des valeurs prises
def write(L):
#on ouvre le fichier data.txt en mode écriture (w)
file = open("data.txt", mode="w")
#on parcourt notre tableau et on ajoute chaque case à chaque ligne du fichierr
for i in range(len(L)):
file.write(L[i]+'\n')
#on ferme le fichier
file.close()

#on appelle la fonction qui va permettre d'écrire dans le fichier texte
write(cleandata)

#on définit la taille de la figure
f = Figure(figsize = (1,0.5), dpi = 25)

#ajout de la figure avec subplot (111 = figure 1 par 1 et figure numéro 1)
a = f.add_subplot(111)
#oon affiche la figure, on prend en compte le fichier data.txt
#ne pas oublier le delimiter, ce qui va séparer chaque valeur, dans ce cas ci c'est un retour à la ligne, donc un espace
a.plot(np.loadtxt("data.txt",delimiter=' ',unpack=True))

#on affiche le Graphe avec en paramètre notre figure f définie avant
#on appelle canvas
canvas = FigureCanvasTkAgg(f, self)
canvas.draw()
#on détermine l'emplacement du graphe s sur la figure
canvas.get_tk_widget().pack(side = tk.TOP, fill=tk.BOTH)
#on affiche un menu en bas de la page avec diverses focntionnalités donc la possibilité d'eregistrer le fichier
toolbar = NavigationToolbar2Tk(canvas, self)
toolbar.update()
#on place la figure, ici elle est placée sur la gauche
canvas._tkcanvas.pack(side = tk.LEFT, fill=tk.BOTH, expand= True)



#on affiche un texte avec label pour demander à l'utilisateur combien de points il souhaite mesurer
texte1 = tk.Label(self, text = "Combien de points souhaitez-vous mesurer ? ", font=LARGE_FONT)
#on place ce texte
texte1.pack()
#espace où l'utilisateur peut rentrer la valeur qu'il souhaite
#petit problème de placement, cette case se place tout en bas de la page et pas nécessairement à coté du label
entree1 = Entry()
#on place cette entrée
entree1.pack()
#on met en place un bouton valider où l'utilisateur vaide son choix
#ce bouton se redirigé vers la fonction getEntry() qui va récupérer ce qui a été indiqué dans la case d'écriture
valid = tk.Button(self, text="Valider", command=getEntry)
valid.pack()

#on place un bouton Actionner
#lorsque ce bouton est enclenché, il actionne la fonction control qui va réaliser ce qui a été expliqué avant
#ainsi, on demandera à l'utilisateur combien de points il souhaite
#puis en appuyant sur le bouton validé, une courbe s'affichera
#ceci se repète tant que l'on appuie sur le bouton Actionner
boutonAction = tk.Button(self, text = "Actionner", command = control)
#placement du bouton Actionner
boutonAction.pack()
#un bouton Revenir à l'accueil permet de rediriger l'utilisateur vers la première page que l'on a appelé StartPage
button1 = tk.Button(self,text = "Revenir à l'accueil", command = lambda: controller.show_frame(StartPage))
button1.pack()
#un bouton Controler les Leds permet de rediriger l'utilisateur vers une nouvelle page que l'on a appelé Page Two
button2 = tk.Button(self,text = "Controler les LEDs", command = lambda: controller.show_frame(PageTwo))
button2.pack()




# ##ICI SE TROUVE UNE FONCTION QUI PERMET DE CALCULER LA MOYENNE DES VALEURS DU FICHIER TEXTE
# # Ouvrir le fichier en lecture seule
# file = open('data.txt', "r")
# # utiliser readlines pour lire toutes les lignes du fichier
# # La variable "lignes" est une liste contenant toutes les lignes du fichier
# lines = file.readlines()
# # fermez le fichier après avoir lu les lignes
# file.close()
# # on additionne chaque ligne grâce à nbr pour obtenir la moyenne
# nbr = 0
# # long permet de calculer la longueur du fichier
# long = 0
# # Itérer sur les lignes
# for line in lines:
# #nbr prend la valeur de chaque ligne du fichier et l'ajoute à son compteur
# nbr += float(line.strip())
# #on calcule le nombre de lignes du fichier, à chaque itération, long prend +1
# long+=1
# #la moyenne vaut toutes la valeurs additionnées entre elles, divisé par le nombre de valeurs (long)
# moy=nbr/long
# #on affiche la moyenne grâce à un label
# moyenne = tk.Label(self, text=("La moyenne de température est",moy), font=LARGE_FONT)
# moyenne.pack()






#PAGE POUR CONTROLER LES LEDS
class PageTwo(tk.Frame):
#initialisation de la page
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
#on affiche un label
label = tk.Label(self, text="Controler les LEDs", font=LARGE_FONT)
label.pack(pady=10, padx=10)
#un bouton pour rediriger vers la page d'accueil appelée Start Page dans le code
button1 = tk.Button(self,text = "Revenir à l'accueil", command = lambda: controller.show_frame(StartPage))
button1.pack()
#Bouton pour rediriger l'utilisateur vers la page permettant d'afficher la température, appelée PageOne
button2 = tk.Button(self,text = "Afficher la température", command = lambda: controller.show_frame(PageOne))
button2.pack()

#on indique le port utilisé
ser = serial.Serial('/dev/ttyACM0',9600)

#une fonction qui permet d'enclencher la led branchée
def on_button():
ser.write(b'1')

#une fonction qui permet d'éteindre la led
def off_button():
ser.write(b'0')


#on définit un bouton
Button = tk.Button
#un premier bouton qui lorsqu'on l'active déclenche la fonction on_button permettant d'allumer la led
btn = Button(self, text="ON", command = on_button)
#un deuxième bouton qui lorsqu'on l'active déclenche la fonction off_button permettant d'éteindre la led
btn1 = Button(self,text="OFF", command = off_button)
#on place ces boutons
btn.pack()
btn1.pack()



#Troisième Page qui permet d'afficher un formulaire
class PageThree(tk.Frame):
#initialisation de la page
def __init__(self,parent,controller):
tk.Frame.__init__(self,parent)
#on affiche un label qui écrit Formulaire en titre
label = tk.Label(self, text = "Formulaire", font = LARGE_FONT)
label.pack(pady=10, padx=10)
#un bouton qui permet de revenir à la page d'accueil, StartPage
button1 = tk.Button(self, text="Back To Home", command=lambda: controller.show_frame(StartPage))
button1.pack()

#on laisse une entrée pour l'utilisateur rentre son nom
nom = Label(self, text="Nom")
e0 = Entry(self)
#on laisse une entrée pour l'utilisateur rentre son prénom
prenom = Label(self, text="Prenom")
e = Entry(self)
nom.pack()
#on place tous ces champs sur la page
e0.pack()
prenom.pack()
e.pack()



#Notre interface prend le nom de la classe principale créée au début, c'est à dire Graphique
app = Graphique()
#on affiche notre interface avec l'instruction mainloop
app.mainloop()





##### !!! si lorsque l'on lance le programme python , l'erreur suivante survient -> ValueError: could not convert string to float: ''
#ouvrir le fichier texte et vérifier qu'une ligne ne soit pas vide, la remplacer avec un chiffre au hasard
#lors du déclenchement du bouton action, ces valeurs seront remplacées par les valeurs mesurées
    (1-1/1)