rc-chuah

calc

Oct 25th, 2021
583
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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. class Calculator:
  15.     def __init__(self):
  16.         self.window = tk.Tk()
  17.         self.window.geometry("375x667")
  18.         self.window.resizable(0, 0)
  19.         self.window.title("Calculator")
  20.  
  21.         self.total_expression = ""
  22.         self.current_expression = ""
  23.         self.display_frame = self.create_display_frame()
  24.  
  25.         self.total_label, self.label = self.create_display_labels()
  26.  
  27.         self.digits = {
  28.             7: (1, 1), 8: (1, 2), 9: (1, 3),
  29.             4: (2, 1), 5: (2, 2), 6: (2, 3),
  30.             1: (3, 1), 2: (3, 2), 3: (3, 3),
  31.             0: (4, 2), '.': (4, 1)
  32.         }
  33.         self.operations = {"/": "\u00F7", "*": "\u00D7", "-": "-", "+": "+"}
  34.         self.buttons_frame = self.create_buttons_frame()
  35.  
  36.         self.buttons_frame.rowconfigure(0, weight=1)
  37.         for x in range(1, 5):
  38.             self.buttons_frame.rowconfigure(x, weight=1)
  39.             self.buttons_frame.columnconfigure(x, weight=1)
  40.         self.create_digit_buttons()
  41.         self.create_operator_buttons()
  42.         self.create_special_buttons()
  43.         self.bind_keys()
  44.  
  45.     def bind_keys(self):
  46.         self.window.bind("<Return>", lambda event: self.evaluate())
  47.         for key in self.digits:
  48.             self.window.bind(str(key), lambda event, digit=key: self.add_to_expression(digit))
  49.  
  50.         for key in self.operations:
  51.             self.window.bind(key, lambda event, operator=key: self.append_operator(operator))
  52.  
  53.     def create_special_buttons(self):
  54.         self.create_clear_button()
  55.         self.create_equals_button()
  56.         self.create_square_button()
  57.         self.create_sqrt_button()
  58.  
  59.     def create_display_labels(self):
  60.         total_label = tk.Label(self.display_frame, text=self.total_expression, anchor=tk.E, bg=LIGHT_GRAY,
  61.                                fg=LABEL_COLOR, padx=24, font=SMALL_FONT_STYLE)
  62.         total_label.pack(expand=True, fill='both')
  63.  
  64.         label = tk.Label(self.display_frame, text=self.current_expression, anchor=tk.E, bg=LIGHT_GRAY,
  65.                          fg=LABEL_COLOR, padx=24, font=LARGE_FONT_STYLE)
  66.         label.pack(expand=True, fill='both')
  67.  
  68.         return total_label, label
  69.  
  70.     def create_display_frame(self):
  71.         frame = tk.Frame(self.window, height=221, bg=LIGHT_GRAY)
  72.         frame.pack(expand=True, fill="both")
  73.         return frame
  74.  
  75.     def add_to_expression(self, value):
  76.         self.current_expression += str(value)
  77.         self.update_label()
  78.  
  79.     def create_digit_buttons(self):
  80.         for digit, grid_value in self.digits.items():
  81.             button = tk.Button(self.buttons_frame, text=str(digit), bg=WHITE, fg=LABEL_COLOR, font=DIGITS_FONT_STYLE,
  82.                                borderwidth=0, command=lambda x=digit: self.add_to_expression(x))
  83.             button.grid(row=grid_value[0], column=grid_value[1], sticky=tk.NSEW)
  84.  
  85.     def append_operator(self, operator):
  86.         self.current_expression += operator
  87.         self.total_expression += self.current_expression
  88.         self.current_expression = ""
  89.         self.update_total_label()
  90.         self.update_label()
  91.  
  92.     def create_operator_buttons(self):
  93.         i = 0
  94.         for operator, symbol in self.operations.items():
  95.             button = tk.Button(self.buttons_frame, text=symbol, bg=OFF_WHITE, fg=LABEL_COLOR, font=DEFAULT_FONT_STYLE,
  96.                                borderwidth=0, command=lambda x=operator: self.append_operator(x))
  97.             button.grid(row=i, column=4, sticky=tk.NSEW)
  98.             i += 1
  99.  
  100.     def clear(self):
  101.         self.current_expression = ""
  102.         self.total_expression = ""
  103.         self.update_label()
  104.         self.update_total_label()
  105.  
  106.     def create_clear_button(self):
  107.         button = tk.Button(self.buttons_frame, text="C", bg=OFF_WHITE, fg=LABEL_COLOR, font=DEFAULT_FONT_STYLE,
  108.                            borderwidth=0, command=self.clear)
  109.         button.grid(row=0, column=1, sticky=tk.NSEW)
  110.  
  111.     def square(self):
  112.         self.current_expression = str(eval(f"{self.current_expression}**2"))
  113.         self.update_label()
  114.  
  115.     def create_square_button(self):
  116.         button = tk.Button(self.buttons_frame, text="x\u00b2", bg=OFF_WHITE, fg=LABEL_COLOR, font=DEFAULT_FONT_STYLE,
  117.                            borderwidth=0, command=self.square)
  118.         button.grid(row=0, column=2, sticky=tk.NSEW)
  119.  
  120.     def sqrt(self):
  121.         self.current_expression = str(eval(f"{self.current_expression}**0.5"))
  122.         self.update_label()
  123.  
  124.     def create_sqrt_button(self):
  125.         button = tk.Button(self.buttons_frame, text="\u221ax", bg=OFF_WHITE, fg=LABEL_COLOR, font=DEFAULT_FONT_STYLE,
  126.                            borderwidth=0, command=self.sqrt)
  127.         button.grid(row=0, column=3, sticky=tk.NSEW)
  128.  
  129.     def evaluate(self):
  130.         self.total_expression += self.current_expression
  131.         self.update_total_label()
  132.         try:
  133.             self.current_expression = str(eval(self.total_expression))
  134.  
  135.             self.total_expression = ""
  136.         except Exception as e:
  137.             self.current_expression = "Error"
  138.         finally:
  139.             self.update_label()
  140.  
  141.     def create_equals_button(self):
  142.         button = tk.Button(self.buttons_frame, text="=", bg=LIGHT_BLUE, fg=LABEL_COLOR, font=DEFAULT_FONT_STYLE,
  143.                            borderwidth=0, command=self.evaluate)
  144.         button.grid(row=4, column=3, columnspan=2, sticky=tk.NSEW)
  145.  
  146.     def create_buttons_frame(self):
  147.         frame = tk.Frame(self.window)
  148.         frame.pack(expand=True, fill="both")
  149.         return frame
  150.  
  151.     def update_total_label(self):
  152.         expression = self.total_expression
  153.         for operator, symbol in self.operations.items():
  154.             expression = expression.replace(operator, f' {symbol} ')
  155.         self.total_label.config(text=expression)
  156.  
  157.     def update_label(self):
  158.         self.label.config(text=self.current_expression[:11])
  159.  
  160.     def run(self):
  161.         self.window.mainloop()
  162.  
  163. if __name__ == "__main__":
  164.     calc = Calculator()
  165.     calc.run()
RAW Paste Data