Advertisement
Guest User

Untitled

a guest
Mar 18th, 2019
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.05 KB | None | 0 0
  1. import tkinter as tk
  2.  
  3. from decimal import Decimal
  4. from tkinter import ttk
  5.  
  6.  
  7. class Calculator(ttk.Frame):
  8. def __init__(self, master=tk.Tk()):
  9. super().__init__(master)
  10. self.master = master
  11. self.master.title("tKalculator")
  12. self.operator = None
  13. self.prev_num = 0
  14. self.completed_calculation = False
  15. self.grid()
  16.  
  17. self.create_widgets()
  18. self.bind_keys()
  19. self.arrange_widgets()
  20.  
  21. self.mainloop()
  22.  
  23. def create_widgets(self):
  24. """
  25. Create all calculator buttons
  26. and widgets
  27. """
  28.  
  29. self.number_buttons = []
  30.  
  31. # Number display
  32. self.top_display_space = ttk.Label(self, text=" ")
  33. self.display = tk.Text(self, height=1, width=30, pady=4)
  34. self.display.insert(1.0, "0")
  35. self.display["state"] = "disabled"
  36. self.bottom_display_space = ttk.Label(self, text=" ")
  37.  
  38. # Number buttons
  39. for num in range(0, 10):
  40. num = str(num)
  41. self.number_buttons.append(
  42. # note to self: The num=num is necessary here
  43. ttk.Button(self, text=num, command=lambda num=num: self.update(num))
  44. )
  45.  
  46. self.decimal_button = ttk.Button(self, text=".",
  47. command=lambda: self.update("."))
  48.  
  49. # Special Buttons
  50. self.clearall_button = ttk.Button(self, text="A/C", command=self.all_clear)
  51. self.clear_button = ttk.Button(self, text="C", command=self.clear)
  52.  
  53. # Math operators
  54. self.add_button = ttk.Button(self, text="+", command=lambda: self.math("+"))
  55. self.sub_button = ttk.Button(self, text="-", command=lambda: self.math("-"))
  56. self.mult_button = ttk.Button(self, text="X", command=lambda: self.math("x"))
  57. self.div_button = ttk.Button(self, text="/", command=lambda: self.math("/"))
  58. self.eql_button = ttk.Button(self, text="=", command=lambda: self.math("="))
  59.  
  60. def arrange_widgets(self):
  61. """
  62. Arrange all calculator widgets.
  63. """
  64.  
  65. # Display
  66. self.top_display_space.grid(row=0, column=1)
  67. self.display.grid(row=1, column=0, columnspan=5)
  68. self.bottom_display_space.grid(row=2, column=2)
  69.  
  70. # Number buttons
  71. row = 3
  72. column = 1
  73. for i in range(1, 10):
  74. self.number_buttons[i].grid(row=row, column=column)
  75. column += 1
  76. if column > 3:
  77. column = 1
  78. row += 1
  79.  
  80. self.number_buttons[0].grid(row=6, column=2)
  81. self.decimal_button.grid(row=6, column=1)
  82.  
  83. # Special Buttons
  84. self.clearall_button.grid(row=7, column=1)
  85. self.clear_button.grid(row=6, column=3)
  86.  
  87. # Math operator buttons
  88. self.add_button.grid(row=7, column=2)
  89. self.sub_button.grid(row=7, column=3)
  90. self.mult_button.grid(row=8, column=2)
  91. self.div_button.grid(row=8, column=3)
  92. self.eql_button.grid(row=8, column=1)
  93.  
  94. def bind_keys(self):
  95. """
  96. Binds events to keyboard button presses.
  97. """
  98.  
  99. # Numbers
  100. self.master.bind("1", self.keypress_handler)
  101. self.master.bind("<KP_1>", self.keypress_handler)
  102. self.master.bind("2", self.keypress_handler)
  103. self.master.bind("<KP_2>", self.keypress_handler)
  104. self.master.bind("3", self.keypress_handler)
  105. self.master.bind("<KP_3>", self.keypress_handler)
  106. self.master.bind("4", self.keypress_handler)
  107. self.master.bind("<KP_4>", self.keypress_handler)
  108. self.master.bind("5", self.keypress_handler)
  109. self.master.bind("<KP_5>", self.keypress_handler)
  110. self.master.bind("6", self.keypress_handler)
  111. self.master.bind("<KP_6>", self.keypress_handler)
  112. self.master.bind("7", self.keypress_handler)
  113. self.master.bind("<KP_7>", self.keypress_handler)
  114. self.master.bind("8", self.keypress_handler)
  115. self.master.bind("<KP_8>", self.keypress_handler)
  116. self.master.bind("9", self.keypress_handler)
  117. self.master.bind("<KP_9>", self.keypress_handler)
  118. self.master.bind("0", self.keypress_handler)
  119. self.master.bind("<KP_0>", self.keypress_handler)
  120. self.master.bind(".", self.keypress_handler)
  121. self.master.bind("<KP_Decimal>", self.keypress_handler)
  122.  
  123. # Special buttons
  124. self.master.bind("c", self.keypress_handler)
  125. self.master.bind("a", self.keypress_handler)
  126. self.master.bind("C", self.keypress_handler)
  127. self.master.bind("A", self.keypress_handler)
  128. self.master.bind("<BackSpace>", self.backspace)
  129.  
  130. # Math operator buttons
  131. self.master.bind("+", self.keypress_handler)
  132. self.master.bind("-", self.keypress_handler)
  133. self.master.bind("*", self.keypress_handler)
  134. self.master.bind("x", self.keypress_handler)
  135. self.master.bind("/", self.keypress_handler)
  136. self.master.bind("<KP_Add>", self.keypress_handler)
  137. self.master.bind("<KP_Subtract>", self.keypress_handler)
  138. self.master.bind("KP_Multiply>", self.keypress_handler)
  139. self.master.bind("<KP_Divide>", self.keypress_handler)
  140.  
  141. # Attempt to math
  142. self.master.bind("<KP_Enter>", self.keypress_handler)
  143. self.master.bind("<Return>", self.keypress_handler)
  144. self.master.bind("=", self.keypress_handler)
  145.  
  146. # Escape to close the calculator
  147. self.master.bind("<Escape>", self.keypress_handler)
  148.  
  149. def backspace(self, event):
  150. """
  151. Remove one character from the display.
  152. """
  153.  
  154. self.display["state"] = "normal"
  155. current = self.display.get(1.0, tk.END)
  156. self.display.delete(1.0, tk.END)
  157. current = current[:-2]
  158.  
  159. # Make sure that the display is never empty
  160. if current == "":
  161. current = "0"
  162.  
  163. self.display.insert(1.0, current)
  164. self.display["state"] = "disabled"
  165.  
  166. def keypress_handler(self, event):
  167. """
  168. Handles any bound keyboard presses.
  169. """
  170.  
  171. char_keycode = '01234567890.'
  172. char_operator = "+-x*/"
  173.  
  174. if (event.char in char_keycode):
  175. self.update(event.char)
  176.  
  177. elif event.char in char_operator:
  178. self.math(event.char)
  179.  
  180. elif event.char == "r" or event.char == "=":
  181. self.math("=")
  182.  
  183. elif event.char == "x1b":
  184. self.master.destroy()
  185.  
  186. elif event.char == "c" or event.char == "C":
  187. self.clear()
  188.  
  189. elif event.char == "a" or event.char == "A":
  190. self.all_clear()
  191.  
  192. def update(self, character):
  193. """
  194. Handles all updating of the number display.
  195. """
  196. # Allow editing of the display
  197. self.display["state"] = "normal"
  198.  
  199. # Get the current number
  200. num = self.display.get(1.0, tk.END)
  201. # clear the display
  202. self.display.delete(1.0, tk.END)
  203.  
  204. # Remove "n"
  205. num = num.strip()
  206.  
  207. # Clear num provided we're not putting a
  208. # decimal after a zero
  209. if num == "0" and not character == ".":
  210. num = ""
  211.  
  212. num = f"{num}{character}"
  213.  
  214. self.display.insert(1.0, f"{num}")
  215. self.display["state"] = "disabled"
  216.  
  217. def all_clear(self):
  218. """
  219. Resets everything for starting a
  220. new calculation.
  221. """
  222. self.clear()
  223. self.prev_num = 0
  224. self.operator = None
  225.  
  226. def clear(self):
  227. """
  228. Clears the display by removing
  229. any current text and setting the
  230. display to 0
  231. """
  232. self.display["state"] = "normal"
  233. self.display.delete(1.0, tk.END)
  234. self.display.insert(1.0, "0")
  235. self.display["state"] = "disabled"
  236.  
  237. def math(self, operator):
  238. """
  239. Handle any actual math.
  240. """
  241. if not self.operator:
  242. # If an operator doesn't exist, the
  243. # calculator is waiting for a new
  244. # input.
  245. self.operator = operator
  246. self.prev_num = self.display.get(1.0, tk.END)
  247. self.clear()
  248.  
  249. else:
  250. # The calculator is ready to do some math.
  251. self.prev_num = Decimal(self.prev_num)
  252. curr_num = self.display.get(1.0, tk.END)
  253. curr_num = Decimal(curr_num)
  254.  
  255. if self.operator == "+":
  256. self.prev_num += curr_num
  257. elif self.operator == "-":
  258. self.prev_num -= curr_num
  259. elif self.operator == "x":
  260. self.prev_num *= curr_num
  261. elif self.operator == "/":
  262. self.prev_num /= curr_num
  263.  
  264. self.operator = operator
  265.  
  266. if self.operator == "=":
  267. # It's now time to show the current result
  268. # of all calculations.
  269. self.display["state"] = "normal"
  270. self.display.delete(1.0, tk.END)
  271. self.display.insert(1.0, str(self.prev_num))
  272. self.display["state"] = "disabled"
  273. self.completed_calculation = True
  274. else:
  275. # We're ready for another number to
  276. # perform calculations on
  277. self.clear()
  278.  
  279. if __name__ == "__main__":
  280. calc = Calculator()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement