1+ from tkinter import *
2+ from math import sqrt as sqr
3+
4+
5+ class Application (Frame ):
6+ """
7+ An example of a calculator app developed using the
8+ Tkinter GUI.
9+ """
10+
11+ def __init__ (self , master ):
12+ """
13+ Initializes the frame.
14+ :param master: root.Tk()
15+ """
16+ Frame .__init__ (self , master )
17+ self .entry = Entry (master , width = 24 , font = ("Arial" ,25 ))
18+ self .entry .grid (row = 0 , column = 0 , columnspan = 6 , sticky = "w" )
19+ self .entry .focus_set ()
20+ self .entry .configure (state = "disabled" , disabledbackground = "white" , disabledforeground = "black" )
21+ self .create_widgets ()
22+ self .bind_buttons (master )
23+ self .grid ()
24+
25+ def add_chr (self , char , btn = None ):
26+ """
27+ Concatenates a character passed from a button press (or key type)
28+ to a string.
29+ :param char: string to add passed from a button
30+ :param btn: button name to use if key is pressed (to flash)
31+ :return: None
32+ """
33+ self .entry .configure (state = "normal" )
34+ self .flash (btn ) # Flash a button correspond to keystroke
35+ if self .entry .get () == "Invalid Input" :
36+ self .entry .delete (0 ,END )
37+ self .entry .insert (END , char )
38+ self .entry .configure (state = "disabled" )
39+
40+ def clear (self ):
41+ """
42+ Allows user to backspace their entry.
43+ :return: None
44+ """
45+ self .entry .configure (state = "normal" )
46+ if self .entry .get () != "Invalid Input" :
47+ # Clears full entry when "Invalid Input"
48+ text = self .entry .get ()[:- 1 ]
49+ self .entry .delete (0 ,END )
50+ self .entry .insert (0 ,text )
51+ else :
52+ self .entry .delete (0 , END )
53+ self .entry .configure (state = "disabled" )
54+
55+ def clear_all (self ):
56+ """
57+ Allows user to clear the full entry.
58+ :return: None
59+ """
60+ self .entry .configure (state = "normal" )
61+ self .entry .delete (0 , END )
62+ self .entry .configure (state = "disabled" )
63+
64+ def calculate (self ):
65+ """
66+ Changes the operation symbols to their mathematical representation used in
67+ the eval() method.
68+ :return: None
69+ """
70+ self .entry .configure (state = "normal" )
71+ e = self .entry .get ()
72+ e = e .replace ("√" ,"sqr" )
73+ e = e .replace ("×" , "*" )
74+ e = e .replace ("²" , "**2" )
75+ e = e .replace ("^" , "**" )
76+ e = e .replace ("÷" , "/" )
77+
78+ try :
79+ ans = eval (e )
80+ except Exception as ex :
81+ self .entry .delete (0 ,END )
82+ self .entry .insert (0 , "Invalid Input" )
83+ else :
84+ self .entry .delete (0 ,END )
85+ if len (str (ans )) > 20 : # Alleviates problem of large numbers
86+ self .entry .insert (0 , '{:.10e}' .format (ans ))
87+ else :
88+ self .entry .insert (0 , ans )
89+ self .entry .configure (state = "disabled" )
90+
91+ def flash (self ,btn ):
92+ """
93+ Flashes a corresponding button when key is pressed.
94+ :param btn: button
95+ :return: None
96+ """
97+ if btn != None :
98+ btn .config (bg = "yellow" )
99+ if btn == self .c_bttn :
100+ self .clear ()
101+ self .master .after (100 , lambda : btn .config (bg = "SystemButtonFace" ))
102+ elif btn == self .eq_bttn :
103+ self .master .after (100 , lambda : btn .config (bg = "lightgrey" ))
104+ self .calculate ()
105+ elif btn == self .ac_bttn :
106+ self .clear_all ()
107+ self .master .after (100 , lambda : btn .config (bg = "SystemButtonFace" ))
108+ else :
109+ self .master .after (100 , lambda : btn .config (bg = "SystemButtonFace" ))
110+ else :
111+ pass
112+
113+ def bind_buttons (self , master ):
114+ """
115+ Binds keys to their appropriate input
116+ :param master: root.Tk()
117+ :return: None
118+ """
119+ master .bind ("<Return>" , lambda event , btn = self .eq_bttn : self .flash (btn ))
120+ master .bind ("<BackSpace>" , lambda event , btn = self .c_bttn : self .flash (btn ))
121+ master .bind ("9" , lambda event , char = "9" , btn = self .nine_bttn : self .add_chr (char , btn ))
122+ master .bind ("8" , lambda event , char = "8" , btn = self .eight_bttn : self .add_chr (char , btn ))
123+ master .bind ("7" , lambda event , char = "7" , btn = self .seven_bttn : self .add_chr (char , btn ))
124+ master .bind ("6" , lambda event , char = "6" , btn = self .six_bttn : self .add_chr (char , btn ))
125+ master .bind ("5" , lambda event , char = "5" , btn = self .five_bttn : self .add_chr (char , btn ))
126+ master .bind ("4" , lambda event , char = "4" , btn = self .four_bttn : self .add_chr (char , btn ))
127+ master .bind ("3" , lambda event , char = "3" , btn = self .three_bttn : self .add_chr (char , btn ))
128+ master .bind ("2" , lambda event , char = "2" , btn = self .two_bttn : self .add_chr (char , btn ))
129+ master .bind ("1" , lambda event , char = "1" , btn = self .one_bttn : self .add_chr (char , btn ))
130+ master .bind ("0" , lambda event , char = "0" , btn = self .zero_bttn : self .add_chr (char , btn ))
131+ master .bind ("*" , lambda event , char = "×" , btn = self .mult_bttn : self .add_chr (char , btn ))
132+ master .bind ("/" , lambda event , char = "÷" , btn = self .div_bttn : self .add_chr (char , btn ))
133+ master .bind ("^" , lambda event , char = "^" , btn = self .sqr_bttn : self .add_chr (char , btn ))
134+ master .bind ("%" , lambda event , char = "%" , btn = self .mod_bttn : self .add_chr (char , btn ))
135+ master .bind ("." , lambda event , char = "." , btn = self .dec_bttn : self .add_chr (char , btn ))
136+ master .bind ("-" , lambda event , char = "-" , btn = self .sub_bttn : self .add_chr (char , btn ))
137+ master .bind ("+" , lambda event , char = "+" , btn = self .add_bttn : self .add_chr (char , btn ))
138+ master .bind ("(" , lambda event , char = "(" , btn = self .lpar_bttn : self .add_chr (char , btn ))
139+ master .bind (")" , lambda event , char = ")" , btn = self .rpar_bttn : self .add_chr (char , btn ))
140+ master .bind ("c" , lambda event , btn = self .ac_bttn : self .flash (btn ), self .clear_all )
141+
142+ def create_widgets (self ):
143+ """
144+ Creates the widgets to be used in the grid.
145+ :return: None
146+ """
147+ self .eq_bttn = Button (self , text = "=" , width = 20 , height = 3 , bg = "lightgrey" , command = lambda : self .calculate ())
148+ self .eq_bttn .grid (row = 4 , column = 4 , columnspan = 2 )
149+
150+ self .ac_bttn = Button (self , text = 'CE' , width = 9 , height = 3 , command = lambda : self .clear_all ())
151+ self .ac_bttn .grid (row = 1 , column = 4 )
152+
153+ self .c_bttn = Button (self , text = '←' , width = 9 , height = 3 , command = lambda : self .clear ())
154+ self .c_bttn .grid (row = 1 , column = 5 )
155+
156+ self .add_bttn = Button (self , text = "+" , width = 9 , height = 3 , command = lambda : self .add_chr ('+' ))
157+ self .add_bttn .grid (row = 4 , column = 3 )
158+
159+ self .mult_bttn = Button (self , text = "×" , width = 9 , height = 3 , command = lambda : self .add_chr ('×' ))
160+ self .mult_bttn .grid (row = 2 , column = 3 )
161+
162+ self .sub_bttn = Button (self , text = "-" , width = 9 , height = 3 , command = lambda : self .add_chr ('-' ))
163+ self .sub_bttn .grid (row = 3 , column = 3 )
164+
165+ self .div_bttn = Button (self , text = "÷" , width = 9 , height = 3 , command = lambda : self .add_chr ('/' ))
166+ self .div_bttn .grid (row = 1 , column = 3 )
167+
168+ self .mod_bttn = Button (self , text = "%" , width = 9 , height = 3 , command = lambda : self .add_chr ('%' ))
169+ self .mod_bttn .grid (row = 4 , column = 2 )
170+
171+ self .seven_bttn = Button (self , text = "7" , width = 9 , height = 3 , command = lambda : self .add_chr (7 ))
172+ self .seven_bttn .grid (row = 1 , column = 0 )
173+
174+ self .eight_bttn = Button (self , text = "8" , width = 9 , height = 3 , command = lambda : self .add_chr (8 ))
175+ self .eight_bttn .grid (row = 1 , column = 1 )
176+
177+ self .nine_bttn = Button (self , text = "9" , width = 9 , height = 3 , command = lambda : self .add_chr (9 ))
178+ self .nine_bttn .grid (row = 1 , column = 2 )
179+
180+ self .four_bttn = Button (self , text = "4" , width = 9 , height = 3 , command = lambda : self .add_chr (4 ))
181+ self .four_bttn .grid (row = 2 , column = 0 )
182+
183+ self .five_bttn = Button (self , text = "5" , width = 9 , height = 3 , command = lambda : self .add_chr (5 ))
184+ self .five_bttn .grid (row = 2 , column = 1 )
185+
186+ self .six_bttn = Button (self , text = "6" , width = 9 , height = 3 , command = lambda : self .add_chr (6 ))
187+ self .six_bttn .grid (row = 2 , column = 2 )
188+
189+ self .one_bttn = Button (self , text = "1" , width = 9 , height = 3 , command = lambda : self .add_chr (1 ))
190+ self .one_bttn .grid (row = 3 , column = 0 )
191+
192+ self .two_bttn = Button (self , text = "2" , width = 9 , height = 3 , command = lambda : self .add_chr (2 ))
193+ self .two_bttn .grid (row = 3 , column = 1 )
194+
195+ self .three_bttn = Button (self , text = "3" , width = 9 , height = 3 , command = lambda : self .add_chr (3 ))
196+ self .three_bttn .grid (row = 3 , column = 2 )
197+
198+ self .zero_bttn = Button (self , text = "0" , width = 9 , height = 3 , command = lambda : self .add_chr (0 ))
199+ self .zero_bttn .grid (row = 4 , column = 0 )
200+
201+ self .dec_bttn = Button (self , text = "." , width = 9 , height = 3 , command = lambda : self .add_chr ('.' ))
202+ self .dec_bttn .grid (row = 4 , column = 1 )
203+
204+ self .lpar_bttn = Button (self , text = "(" , width = 9 , height = 3 , command = lambda : self .add_chr ('(' ))
205+ self .lpar_bttn .grid (row = 2 , column = 4 )
206+
207+ self .rpar_bttn = Button (self , text = ")" , width = 9 , height = 3 , command = lambda : self .add_chr (')' ))
208+ self .rpar_bttn .grid (row = 2 , column = 5 )
209+
210+ self .sq_bttn = Button (self , text = "√" , width = 9 , height = 3 , command = lambda : self .add_chr ('√(' ))
211+ self .sq_bttn .grid (row = 3 , column = 4 )
212+
213+ self .sqr_bttn = Button (self , text = "^" , width = 9 , height = 3 , command = lambda : self .add_chr ('^' ))
214+ self .sqr_bttn .grid (row = 3 , column = 5 )
215+
216+ root = Tk ()
217+ root .geometry ()
218+ root .title ("Exciting GUI Calculator" )
219+ app = Application (root )
220+ root .mainloop ()
0 commit comments