@ -1,11 +1,10 @@
import tkinter as tk
from tkinter import messagebox , font
from tkinter import messagebox
from Pile import Pile_chaine as Pile
from math import *
from expression import *
from infixe import infixe2npi
from popup import MsgBox
class ValeurSaisie :
""" classe d ' une valeur saise par l ' utilisateur """
@ -24,7 +23,7 @@ class Interface(tk.Frame):
def __init__ ( self , master ) :
self . master = master
tk . Frame . __init__ ( self , master )
self . etat = tk . Label ( self . master , text = " notation postfixée (polonaise inversée) -- mode interactif " , fg = " gray42 " )
self . etat . pack ( )
self . etat_affichage = " post-int "
@ -40,9 +39,9 @@ class Interface(tk.Frame):
self . affichage_expression . pack ( )
frame_saisie = tk . Frame ( self . master , padx = 5 , pady = 5 )
frame_saisie . pack ( )
frame_saisie . pack ( fill = " both " )
self . saisie_expression = tk . Entry ( frame_saisie )
self . saisie_expression . pack ( side = " left " )
self . saisie_expression . pack ( fill = " both " , expand = True , side = " left " )
self . saisie_expression . bind ( " <Return> " , lambda e : self . entrer ( ) )
self . saisie_expression . bind ( " <KP_Enter> " , lambda e : self . entrer ( ) )
@ -50,29 +49,39 @@ class Interface(tk.Frame):
btn_entrer . pack ( )
commandes = tk . LabelFrame ( self . master , text = " commandes " , padx = 5 , pady = 5 )
commandes . pack ( fill = " both " )
commandes . pack ( fill = " both " , padx = 5 )
self . frame_pile = tk . LabelFrame ( commandes , text = " pile " , padx = 5 , pady = 5 )
self . frame_pile . pack ( fill = " both " )
tk . Button ( self . frame_pile , text = ' tout supprimer ' , command = self . effacer_tt ) . pack ( side = " left " )
tk . Button ( self . frame_pile , text = ' supprimer sommet ' , command = self . effacer_dernier ) . pack ( side = " left " )
tk . Button ( self . frame_pile , text = ' dupliquer sommet ' , command = self . dupliquer ) . pack ( side = " left " )
effacer = tk . LabelFrame ( commandes , text = " effacer " , padx = 5 , pady = 5 )
effacer . pack ( fill = " both " )
btn_effacer_tt = tk . Button ( effacer , text = ' tout effacer ' , command = self . effacer_tt )
btn_effacer_tt . pack ( side = " left " )
btn_effacer_dernier = tk . Button ( effacer , text = ' effacer la dernière valeur ' , command = self . effacer_dernier )
btn_effacer_dernier . pack ( side = " left " )
fonctions = tk . LabelFrame ( commandes , text = " fonctions " , padx = 5 , pady = 5 )
fonctions . pack ( fill = " both " )
btn_sinus = tk . Button ( fonctions , text = ' sin ' , command = lambda : self . evaluer_stack ( " sin " , 1 ) )
btn_sinus . pack ( side = " left " )
btn_sinus = tk . Button ( fonctions , text = ' cos ' , command = lambda : self . evaluer_stack ( " cos " , 1 ) )
btn_sinus . pack ( side = " left " )
btn_sinus = tk . Button ( fonctions , text = ' tan ' , command = lambda : self . evaluer_stack ( " tan " , 1 ) )
btn_sinus . pack ( side = " left " )
btn_pow = tk . Button ( fonctions , text = ' ^ ' , command = lambda : self . evaluer_stack ( " ^ " , 2 ) )
btn_pow . pack ( side = " right " )
for i , text in enumerate ( ( " + " , " - " , " / " , " * " , " ^ " ) ) :
tk . Button ( fonctions , text = text , command = lambda x = text : self . ecrire_fx ( x ) ) . grid ( row = 0 , column = i , sticky = " ew " )
for i , text in enumerate ( ( " sin " , " cos " , " tan " , " factorielle " ) ) :
tk . Button ( fonctions , text = text , command = lambda x = text : self . ecrire_fx ( x ) ) . grid ( row = 1 , column = i , sticky = " ew " )
for i , text in enumerate ( ( " asin " , " acos " , " atan " ) ) :
tk . Button ( fonctions , text = text , command = lambda x = text : self . ecrire_fx ( x ) ) . grid ( row = 2 , column = i , sticky = " ew " )
def ecrire_fx ( self , nom ) :
self . saisie_expression . insert ( tk . END , " " + nom + " " )
if self . etat_affichage == " post-int " :
self . entrer ( )
def dupliquer ( self ) :
if not self . stack . est_vide ( ) :
self . stack . empiler ( ValeurSaisie ( self . stack . sommet ( ) . valeur , self . frame_stack ) )
def create_menu_bar ( self ) :
""" crée la barre de menu de la calculatrice """
menu_bar = tk . Menu ( self )
menu_file = tk . Menu ( menu_bar , tearoff = 0 )
@ -98,7 +107,9 @@ class Interface(tk.Frame):
self . master . config ( menu = menu_bar )
def change_affichage ( self , affichage ) :
""" change le mode d ' affichage et efface les calculs en cours """
""" change le mode d ' affichage,
désactive les opérations de pile si pas dans le mode interactif
et efface les calculs en cours """
self . etat_affichage = affichage
etat_text = { " pre " : " notation préfixée (polonaise) " ,
@ -108,6 +119,13 @@ class Interface(tk.Frame):
}
self . etat . config ( text = etat_text [ affichage ] )
if self . etat_affichage != " post-int " :
for child in self . frame_pile . winfo_children ( ) :
child . configure ( state = ' disable ' )
else :
for child in self . frame_pile . winfo_children ( ) :
child . configure ( state = ' normal ' )
self . affichage_expression . config ( text = " " )
self . effacer_tt ( )
self . saisie_expression . delete ( 0 , ' end ' )
@ -121,31 +139,39 @@ class Interface(tk.Frame):
def entrer ( self ) :
""" si dans mode interactif alors ajoute nv terme
si dans autre mode alors evalue l ' expression " " "
if self . etat_affichage == " post-int " :
self . entrer_terme_dans_stack ( )
if len ( self . saisie_expression . get ( ) ) > 0 :
self . evaluer_expr ( )
try :
if len ( self . saisie_expression . get ( ) ) > 0 :
if self . etat_affichage == " post-int " :
try : self . entrer_terme_dans_stack ( self . saisie_expression . get ( ) . replace ( " " , " " ) )
except ValueError :
messagebox . showerror ( " Saisie invalide " , " Le résultat n ' est pas un nombre réel. " )
else :
self . evaluer_expr ( )
except OverflowError :
messagebox . showerror ( " OverflowError " , " Le résultat est trop élevé. " )
def entrer_terme_dans_stack ( self ) :
def entrer_terme_dans_stack ( self , terme ) :
""" si nombre : ajoute une nouvelle valeur dans le stack
ajoute un label avec cette valeur
si fonction : on l ' évalue " " "
valeur_a_ajouter = self . saisie_expression . get ( ) . replace ( " " , " " )
if valeur_a_ajouter != " " :
if " . " in valeur_a_ajouter :
valeur_a_ajouter = float ( valeur_a_ajouter )
self . stack . empiler ( ValeurSaisie ( valeur_a_ajouter , self . frame_stack ) )
elif valeur_a_ajouter in [ " sin " , " cos " , " tan " , " sqrt " , " ! " , " opp " ] : self . evaluer_stack ( valeur_a_ajouter , 1 )
elif valeur_a_ajouter in [ " + " , " - " , " / " , " * " , " ^ " ] : self . evaluer_stack ( valeur_a_ajouter , 2 )
elif valeur_a_ajouter in [ " moy3 " ] : self . evaluer_stack ( valeur_a_ajouter , 3 )
elif valeur_a_ajouter in [ " somme " , " produit " ] : self . evaluer_stack ( valeur_a_ajouter , - 1 )
elif valeur_a_ajouter == " pi " : self . stack . empiler ( ValeurSaisie ( pi , self . frame_stack ) )
else :
try :
valeur_a_ajouter = int ( valeur_a_ajouter )
self . stack . empiler ( ValeurSaisie ( valeur_a_ajouter , self . frame_stack ) )
except ValueError :
messagebox . showerror ( " Saisie invalide " , " Vous n ' avez pas entré un nombre, ou la fonction est inconnue " )
if " . " in terme :
terme = float ( terme )
self . stack . empiler ( ValeurSaisie ( terme , self . frame_stack ) )
elif terme in [ " asin " , " acos " , " atan " , " sin " , " cos " , " tan " , " sqrt " , " ! " , " factorielle " , " opp " ] : self . evaluer_stack ( terme , 1 )
elif terme in [ " + " , " - " , " / " , " * " , " ^ " ] : self . evaluer_stack ( terme , 2 )
elif terme in [ " moy3 " ] : self . evaluer_stack ( terme , 3 )
elif terme in [ " somme " , " produit " ] : self . evaluer_stack ( terme , - 1 )
elif terme == " pi " : self . stack . empiler ( ValeurSaisie ( pi , self . frame_stack ) )
elif terme == " e " : self . stack . empiler ( ValeurSaisie ( exp ( 1 ) , self . frame_stack ) )
else :
try :
terme = int ( terme )
self . stack . empiler ( ValeurSaisie ( terme , self . frame_stack ) )
except ValueError :
messagebox . showerror ( " Saisie invalide " , " Vous n ' avez pas entré un nombre, ou la fonction est inconnue " )
return
self . saisie_expression . delete ( 0 , ' end ' )
@ -182,8 +208,11 @@ class Interface(tk.Frame):
if op == " sin " : res = sin ( val )
if op == " cos " : res = cos ( val )
if op == " tan " : res = tan ( val )
if op == " asin " : res = asin ( val )
if op == " acos " : res = acos ( val )
if op == " atan " : res = atan ( val )
if op == " sqrt " : res = sqrt ( val )
if op == " ! " : res = factorial ( val )
if op == " ! " or op == " factorielle " : res = factorial ( val )
if op == " opp " : res = - val
elif nb_arg == 2 :
@ -212,26 +241,29 @@ class Interface(tk.Frame):
if self . etat_affichage == " pre " :
lst_expr . reverse ( )
if self . etat_affichage == " inf " :
if " opp " in lst_expr :
messagebox . showerror ( " Erreur " , " Vous ne pouvez pas utiliser la fonction ' opp ' ici ; veuillez utiliser le signe ' - ' à la place. \n (Vous pouvez par contre utiliser ' opp ' quand vous êtes en notation préfixée ou infixée.) " )
return
try :
lst_expr = infixe2npi ( lst_expr )
except SyntaxError as s :
explication , i_char = s . args [ 0 ]
if explication == " manque op " :
messagebox . showerror ( " Erreur de syntaxe " ,
" Il manque un opérateur. L ' étoile ( « ★ » ) indique la position de l ' opérateur manquant dans l ' expression. "
+ "\n L ' expression : \n \n ( "
+ " ". join ( lst_expr [ : i_char ] ) + " ) ★ ( " + " ". join ( lst_expr [ i_char : ] ) + " ) ")
elif explication == " Mauvais () detail " :
messagebox . showerror ( " Erreur de syntaxe " , explication
+ "\n La parenthèse fautive entre 【 crochet 】: \n \n "
+ " ". join ( lst_expr [ : i_char ] )
+ " 【 " + str ( lst_expr [ i_char ] ) + " 】 " + " ". join ( lst_expr [ i_char + 1 : ] ) )
else :
messagebox . showerror ( " Erreur de syntaxe " , explication )
return
#except SyntaxError as s :
# explication, i_char = s.args[0 ]
# if explication == "manque op" :
# messagebox.showerror("Erreur de syntaxe" ,
# "Il manque un opérateur. L'étoile ( « ★ » ) indique la position de l'opérateur manquant dans l'expression."
# + "\nL'expression : \n\n("
# + " ".join(lst_expr[:i_char]) + ") ★ (" + " ".join(lst_expr[i_char:]) + ")")
# elif explication == "Mauvais () detail" :
# messagebox.showerror("Erreur de syntaxe", explication
# + "\nLa parenthèse fautive entre 【 crochet 】: \n\n"
# + " ".join(lst_expr[:i_char])
# + " 【 " + str(lst_expr[i_char]) + " 】 " + " ".join(lst_expr[i_char+1:]))
# else :
# messagebox.showerror("Erreur de syntaxe", explication )
# return
except ValueError as v :
message , explication , i_char = v . args
messagebox . showerror ( message , " Le terme « " + lst_expr [ i_char ] + " » "
+ explication + " \n \n "
+ " Dans l ' expression, entre 【 crochet 】 : \n " + " " . join ( lst_expr [ : i_char ] )
@ -243,20 +275,22 @@ class Interface(tk.Frame):
self . affichage_expression . config ( text = str ( arbre_expr ) + " = " + str ( arbre_expr . evalue ( ) ) )
except IndexError :
messagebox . showerror ( " Erreur " , " Erreur de syntaxe ici " )
except ValueError :
#faire un truc plus beau
messagebox . showerror ( " Saisie invalide " , " Vous n ' avez pas entré un nombre, ou la fonction est inconnue. " )
except ValueError as v :
explication = v . args [ 0 ]
if v . args [ 0 ] == " math domain error " :
messagebox . showerror ( " Saisie invalide " , " Le résultat n ' est pas un nombre réel. " )
else :
message , explication , i_char = v . args
if self . etat_affichage == " pre " :
lst_expr . reverse ( )
i_char = len ( lst_expr ) - i_char - 1
messagebox . showerror ( message , " Le terme « " + lst_expr [ i_char ] + " » "
+ explication + " \n \n "
+ " Dans l ' expression, entre 【 crochet 】 : \n " + " " . join ( lst_expr [ : i_char ] )
+ " 【 " + str ( lst_expr [ i_char ] ) + " 】 " + " " . join ( lst_expr [ i_char + 1 : ] ) )
except SyntaxError as s :
explication , pile_expr = s . args [ 0 ]
print ( " pile_expr depuis evaluer_expr " , pile_expr )
lst_pile_expr = [ ]
while not pile_expr . est_vide ( ) :
lst_pile_expr . append ( str ( pile_expr . depiler ( ) ) )
lst_pile_expr . reverse ( )
print ( lst_pile_expr )
messagebox . showerror ( " Erreur de syntaxe " , explication
+ " \n L ' expression : \n \n ( "
+ " ) ★ ( " . join ( lst_pile_expr ) + " ) " )
explication = s . args [ 0 ]
messagebox . showerror ( " Erreur de syntaxe " , explication )
def effacer_tt ( self ) :
""" supprime tout le contenu de la pile (et les labels associés) """
@ -273,6 +307,6 @@ class Interface(tk.Frame):
if __name__ == " __main__ " :
root = tk . Tk ( )
root . title ( " Calculatrice " )
root . geometry ( " 35 0x500 " )
root . geometry ( " 38 0x500 " )
hello_frame = Interface ( root )
hello_frame . mainloop ( )