Skip to content

Instantly share code, notes, and snippets.

@TheRealYT
Last active August 1, 2023 12:16
Show Gist options
  • Save TheRealYT/414bfad16cfb81114b210601a0df78a6 to your computer and use it in GitHub Desktop.
Save TheRealYT/414bfad16cfb81114b210601a0df78a6 to your computer and use it in GitHub Desktop.
Python GUI Calculator
"""
Copyright 2023 Yonathan Tesfaye
Github: https://github.com/TheRealYT
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Basic gui calculator based on python libraries, tested on Python v3.9.0 on windows 10
"""
from tkinter import *
from tkinter import ttk
import re
width = 280
height = 420
boxHeight = 70
buttonWidth = 70
buttonHeight = 70
class App(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.init()
self.operator = StringVar()
self.num_old = StringVar()
self.num_input = StringVar()
self.operators = {
'/': (lambda a, b: "ZeroDivisionError" if (b == 0) else a / b),
'*': (lambda a, b: a * b),
'-': (lambda a, b: a - b),
'+': (lambda a, b: a + b),
'%': (lambda a, b: a % b)
}
ttk.Label(master, textvariable=self.num_input, anchor="e", background="#fff", padding=15).place(
height=boxHeight, width=width)
Label(master, textvariable=self.num_old, anchor="center", background="#fff").place(x=0, y=0)
Label(master, textvariable=self.operator, anchor="center", background="#fff").place(x=width - 15, y=0)
self.col_row_buttons([
[
Button(master, text="C", fg="black", command=lambda: self.exec("CLEAR")),
Button(master, text="7", fg="black", command=lambda: self.exec("7")),
Button(master, text="4", fg="black", command=lambda: self.exec("4")),
Button(master, text="1", fg="black", command=lambda: self.exec("1")),
Button(master, text="+/-", fg="black", command=lambda: self.exec("SIGN"))
],
[
Button(master, text="CE", fg="black", command=lambda: self.exec("CLEAR_E")),
Button(master, text="8", fg="black", command=lambda: self.exec("8")),
Button(master, text="5", fg="black", command=lambda: self.exec("5")),
Button(master, text="2", fg="black", command=lambda: self.exec("2")),
Button(master, text="0", fg="black", command=lambda: self.exec("0"))
],
[
Button(master, text="%", fg="black", command=lambda: self.exec("%")),
Button(master, text="9", fg="black", command=lambda: self.exec("9")),
Button(master, text="6", fg="black", command=lambda: self.exec("6")),
Button(master, text="3", fg="black", command=lambda: self.exec("3")),
Button(master, text=".", fg="black", command=lambda: self.exec("."))
],
[
Button(master, text="/", fg="black", command=lambda: self.exec("/")),
Button(master, text="*", fg="black", command=lambda: self.exec("*")),
Button(master, text="-", fg="black", command=lambda: self.exec("-")),
Button(master, text="+", fg="black", command=lambda: self.exec("+")),
Button(master, text="=", fg="black", command=lambda: self.exec("="))
]
], 0, 0)
@staticmethod
def row_buttons(buttons, offset_x=0, offset_y=0, col=1, row=1):
for i in range(len(buttons)):
buttons[i].place(x=((i * col) + offset_x) * buttonWidth, y=boxHeight + (offset_y * buttonHeight),
width=buttonWidth * col, height=buttonHeight * row)
@staticmethod
def col_buttons(buttons, offset_x=0, offset_y=0, col=1, row=1):
for i in range(len(buttons)):
buttons[i].place(x=offset_x * buttonWidth, y=boxHeight + (((i * row) + offset_y) * buttonHeight),
width=buttonWidth * col, height=buttonHeight * row)
def row_col_buttons(self, buttons, offset_x=0, offset_y=0, col=1, row=1):
for i in range(len(buttons)):
self.row_buttons(buttons[i], offset_x=offset_x, offset_y=offset_y + i, col=col, row=row)
def col_row_buttons(self, buttons, offset_x=0, offset_y=0, col=1, row=1):
for i in range(len(buttons)):
self.col_buttons(buttons[i], offset_x=offset_x + i, offset_y=offset_y, col=col, row=row)
def exec(self, value=""):
if re.match(r'^[a-z]+$', self.num_input.get().lower()):
self.num_input.set("")
if re.match(r'^[0-9.]+$', value):
if self.num_input.get() == "0":
if value == "0":
return
else:
self.num_input.set("")
elif value == ".":
if "." in self.num_input.get():
return
elif self.num_input.get() == "":
self.num_input.set("0")
self.num_input.set(self.num_input.get() + value)
elif re.match(r'^[/*\-+%=]$', value):
if value == "=":
if self.operator.get() != "" and self.num_input.get() != "":
self.calc()
elif self.num_input.get() != "" or self.num_old.get() != "":
self.operator.set(value)
if self.num_old.get() == "":
self.num_old.set(self.num_input.get())
self.num_input.set("")
elif value == "SIGN":
if self.num_input.get() != "":
self.num_input.set(str(-1 * self.parse(self.num_input.get())))
elif value == "CLEAR":
self.num_old.set("")
self.num_input.set("")
self.operator.set("")
elif value == "CLEAR_E":
self.num_input.set("")
def calc(self):
a = self.parse(self.num_old.get())
b = self.parse(self.num_input.get())
self.num_old.set("")
self.num_input.set(self.operators[self.operator.get()](a, b))
self.operator.set("")
@staticmethod
def parse(num_str):
if num_str == "":
return 0
return float(num_str) if ("." in num_str) else int(num_str)
def init(self):
self.master.title("Calculator")
self.master.minsize(width, height)
self.master.maxsize(width, height)
# create the application
root = Tk()
app = App(root)
# start the program
app.mainloop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment