├── .gitignore ├── calculator.png ├── README.md └── calc.py /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ -------------------------------------------------------------------------------- /calculator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programiz/Calculator/HEAD/calculator.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Calculator 2 | Create your own Python Calculator App using Python and tkinter. 3 | 4 | Video Link: [https://youtu.be/QZPv1y2znZo](https://youtu.be/QZPv1y2znZo) 5 | 6 | ![Calculator App](calculator.png) 7 | 8 | --- 9 | 10 | ## Create Standalone Executable 11 | 12 | ```shell 13 | pip install pyinstaller 14 | pyinstaller --onefile -w calc.py 15 | ``` 16 | -------------------------------------------------------------------------------- /calc.py: -------------------------------------------------------------------------------- 1 | import tkinter as tk 2 | 3 | LARGE_FONT_STYLE = ("Arial", 40, "bold") 4 | SMALL_FONT_STYLE = ("Arial", 16) 5 | DIGITS_FONT_STYLE = ("Arial", 24, "bold") 6 | DEFAULT_FONT_STYLE = ("Arial", 20) 7 | 8 | OFF_WHITE = "#F8FAFF" 9 | WHITE = "#FFFFFF" 10 | LIGHT_BLUE = "#CCEDFF" 11 | LIGHT_GRAY = "#F5F5F5" 12 | LABEL_COLOR = "#25265E" 13 | 14 | 15 | class Calculator: 16 | def __init__(self): 17 | self.window = tk.Tk() 18 | self.window.geometry("375x667") 19 | self.window.resizable(0, 0) 20 | self.window.title("Calculator") 21 | 22 | self.total_expression = "" 23 | self.current_expression = "" 24 | self.display_frame = self.create_display_frame() 25 | 26 | self.total_label, self.label = self.create_display_labels() 27 | 28 | self.digits = { 29 | 7: (1, 1), 8: (1, 2), 9: (1, 3), 30 | 4: (2, 1), 5: (2, 2), 6: (2, 3), 31 | 1: (3, 1), 2: (3, 2), 3: (3, 3), 32 | 0: (4, 2), '.': (4, 1) 33 | } 34 | self.operations = {"/": "\u00F7", "*": "\u00D7", "-": "-", "+": "+"} 35 | self.buttons_frame = self.create_buttons_frame() 36 | 37 | self.buttons_frame.rowconfigure(0, weight=1) 38 | for x in range(1, 5): 39 | self.buttons_frame.rowconfigure(x, weight=1) 40 | self.buttons_frame.columnconfigure(x, weight=1) 41 | self.create_digit_buttons() 42 | self.create_operator_buttons() 43 | self.create_special_buttons() 44 | self.bind_keys() 45 | 46 | def bind_keys(self): 47 | self.window.bind("", lambda event: self.evaluate()) 48 | for key in self.digits: 49 | self.window.bind(str(key), lambda event, digit=key: self.add_to_expression(digit)) 50 | 51 | for key in self.operations: 52 | self.window.bind(key, lambda event, operator=key: self.append_operator(operator)) 53 | 54 | def create_special_buttons(self): 55 | self.create_clear_button() 56 | self.create_equals_button() 57 | self.create_square_button() 58 | self.create_sqrt_button() 59 | 60 | def create_display_labels(self): 61 | total_label = tk.Label(self.display_frame, text=self.total_expression, anchor=tk.E, bg=LIGHT_GRAY, 62 | fg=LABEL_COLOR, padx=24, font=SMALL_FONT_STYLE) 63 | total_label.pack(expand=True, fill='both') 64 | 65 | label = tk.Label(self.display_frame, text=self.current_expression, anchor=tk.E, bg=LIGHT_GRAY, 66 | fg=LABEL_COLOR, padx=24, font=LARGE_FONT_STYLE) 67 | label.pack(expand=True, fill='both') 68 | 69 | return total_label, label 70 | 71 | def create_display_frame(self): 72 | frame = tk.Frame(self.window, height=221, bg=LIGHT_GRAY) 73 | frame.pack(expand=True, fill="both") 74 | return frame 75 | 76 | def add_to_expression(self, value): 77 | self.current_expression += str(value) 78 | self.update_label() 79 | 80 | def create_digit_buttons(self): 81 | for digit, grid_value in self.digits.items(): 82 | button = tk.Button(self.buttons_frame, text=str(digit), bg=WHITE, fg=LABEL_COLOR, font=DIGITS_FONT_STYLE, 83 | borderwidth=0, command=lambda x=digit: self.add_to_expression(x)) 84 | button.grid(row=grid_value[0], column=grid_value[1], sticky=tk.NSEW) 85 | 86 | def append_operator(self, operator): 87 | self.current_expression += operator 88 | self.total_expression += self.current_expression 89 | self.current_expression = "" 90 | self.update_total_label() 91 | self.update_label() 92 | 93 | def create_operator_buttons(self): 94 | i = 0 95 | for operator, symbol in self.operations.items(): 96 | button = tk.Button(self.buttons_frame, text=symbol, bg=OFF_WHITE, fg=LABEL_COLOR, font=DEFAULT_FONT_STYLE, 97 | borderwidth=0, command=lambda x=operator: self.append_operator(x)) 98 | button.grid(row=i, column=4, sticky=tk.NSEW) 99 | i += 1 100 | 101 | def clear(self): 102 | self.current_expression = "" 103 | self.total_expression = "" 104 | self.update_label() 105 | self.update_total_label() 106 | 107 | def create_clear_button(self): 108 | button = tk.Button(self.buttons_frame, text="C", bg=OFF_WHITE, fg=LABEL_COLOR, font=DEFAULT_FONT_STYLE, 109 | borderwidth=0, command=self.clear) 110 | button.grid(row=0, column=1, sticky=tk.NSEW) 111 | 112 | def square(self): 113 | self.current_expression = str(eval(f"{self.current_expression}**2")) 114 | self.update_label() 115 | 116 | def create_square_button(self): 117 | button = tk.Button(self.buttons_frame, text="x\u00b2", bg=OFF_WHITE, fg=LABEL_COLOR, font=DEFAULT_FONT_STYLE, 118 | borderwidth=0, command=self.square) 119 | button.grid(row=0, column=2, sticky=tk.NSEW) 120 | 121 | def sqrt(self): 122 | self.current_expression = str(eval(f"{self.current_expression}**0.5")) 123 | self.update_label() 124 | 125 | def create_sqrt_button(self): 126 | button = tk.Button(self.buttons_frame, text="\u221ax", bg=OFF_WHITE, fg=LABEL_COLOR, font=DEFAULT_FONT_STYLE, 127 | borderwidth=0, command=self.sqrt) 128 | button.grid(row=0, column=3, sticky=tk.NSEW) 129 | 130 | def evaluate(self): 131 | self.total_expression += self.current_expression 132 | self.update_total_label() 133 | try: 134 | self.current_expression = str(eval(self.total_expression)) 135 | 136 | self.total_expression = "" 137 | except Exception as e: 138 | self.current_expression = "Error" 139 | finally: 140 | self.update_label() 141 | 142 | def create_equals_button(self): 143 | button = tk.Button(self.buttons_frame, text="=", bg=LIGHT_BLUE, fg=LABEL_COLOR, font=DEFAULT_FONT_STYLE, 144 | borderwidth=0, command=self.evaluate) 145 | button.grid(row=4, column=3, columnspan=2, sticky=tk.NSEW) 146 | 147 | def create_buttons_frame(self): 148 | frame = tk.Frame(self.window) 149 | frame.pack(expand=True, fill="both") 150 | return frame 151 | 152 | def update_total_label(self): 153 | expression = self.total_expression 154 | for operator, symbol in self.operations.items(): 155 | expression = expression.replace(operator, f' {symbol} ') 156 | self.total_label.config(text=expression) 157 | 158 | def update_label(self): 159 | self.label.config(text=self.current_expression[:11]) 160 | 161 | def run(self): 162 | self.window.mainloop() 163 | 164 | 165 | if __name__ == "__main__": 166 | calc = Calculator() 167 | calc.run() 168 | --------------------------------------------------------------------------------