menator01
Gold Coder
Can use either button or keyboard. esc will clear and either return key will calculate. Very few bug checks. So may run into one here and there.
Python:
import tkinter as tk
from decimal import Decimal
class Window(tk.Tk):
''' Class creates the display window '''
def __init__(self):
super().__init__()
self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
self.resizable(False, False)
self.title('Tkinter Basic Calculator')
# Create a textvariable for entry manipulation
self.var = tk.StringVar()
self.entry = tk.Entry(self, textvariable=self.var, font=(None, 12))
self.entry.grid(column=0, row=0, sticky='we', padx=5, pady=3)
self.entry.insert('end', '0')
# Sert focus on the entry widget
self.entry.focus()
# Create container for buttons
btn_container = tk.Frame(self)
btn_container.grid(column=0, row=1, sticky='news')
for i in range(3):
btn_container.grid_columnconfigure(i, weight=3, uniform='button')
# Create the dgits for button text
digits = [i for i in range(1, 10)]
# Empty list to hold buttons and some variables for columns and rows
buttons = []
i = 0
col, row = 0, 0
# 1x1 image
pixel = tk.PhotoImage(width=1, height=1)
# Keep a reference of image
pixel.backup = pixel # Note button will not work without this
# Create the buttons
for button in digits:
buttons.append(tk.Button(btn_container, text=button, width=74, height=15))
buttons[i]['image'] = pixel
buttons[i]['compound'] = 'left'
buttons[i]['cursor'] = 'hand2'
buttons[i]['command'] = lambda btn=buttons[i]['text']: self.pressed(btn)
buttons[i].grid(column=col, row=row, padx=2, pady=2)
# Increatment for each loop through
i += 1
# Set columns and rows
if col >= 2:
row += 1
col = 0
else:
col += 1
# Create the zeo button
zero = tk.Button(btn_container, text='0', image=pixel, cursor='hand2', compound='center')
zero.grid(column=0, row=3, sticky='we', padx=2, pady=2)
zero.configure(command=lambda val='0': self.pressed(val))
# Button to clear tthe label text
clear_btn = tk.Button(btn_container, text='Clear', width=74, height=15, compound='center', command=self.clear)
clear_btn.grid(column=0, columnspan=4, row=4, sticky='new', padx=2, pady=2)
clear_btn.configure(cursor='hand2', bg='tomato', activebackground='red', fg='white', activeforeground='white',
image=pixel, font=(None, 12, 'bold'))
# Create the decimal/period button
self.period = tk.Button(btn_container, text='.', anchor='s', width=74, height=15, image=pixel, compound='center')
self.period.grid(column=1, row=3, sticky='we', padx=2, pady=2, ipady=1)
self.period.configure(font=(None, 24), command=lambda val='.': self.pressed(val), cursor='hand2')
# Create the equal button
self.eq_btn = tk.Button(btn_container, text='=', width=74, height=15, image=pixel, compound='center')
self.eq_btn.grid(column=2, row=3, sticky='we', padx=2, pady=2)
self.eq_btn.configure(font=(None, 24), command=lambda: self.calculate(), cursor='hand2')
# Create list of symbols
symb = ['x','/','+','-']
# Empty list to hold symbols buttons
symbols = []
for i in range(len(symb)):
button = tk.Button(btn_container, text=symb[i], cursor='hand2')
symbols.append(button)
symbols[i]['command'] = lambda symbol=button.cget('text'): self.pressed(symbol)
symbols[i].grid(column=3, row=i, sticky='we', padx=2, pady=2)
symbols[i].configure(font=(None, 18), width=74, height=15, image=pixel, compound='center')
# Bind some buttons
self.bind('<Return>', self.calculate)
self.bind('<KP_Enter>', self.calculate)
self.bind('<Escape>', self.clear)
# Using trace to manipulate the the entry field
self.var.trace('w', self.change)
# Check for valid input
valid = self.register(self.valid)
self.entry.configure(validate='key', validatecommand=(valid, '%S'))
def valid(self, arg):
''' Method for validating characters insert. We only want numbers
or calculation symbols '''
if arg == 'x':
return True
elif arg.isalpha() or arg == '=':
return False
else:
return True
def change(self, var, mode, index):
''' Method will replace * with x for the multiply symbol '''
var = self.var.get()
var = var.replace('*', 'x')
# If there is a leading zero replace with entry
if self.var.get()[:-1] == '0' and len(var) ==2:
var = self.var.get()[1:]
self.entry.delete(0, 'end')
self.entry.insert('end', var)
# method for the buttons
def pressed(self, btn):
''' Method places pressed button keys into the entry field '''
self.entry.insert('end', btn)
def calculate(self, event=None):
''' Method for calaculting results '''
values = self.entry.get()
# If x in the calculation replace with *
if 'x' in values:
values = values.replace('x', '*')
result = eval(values)
# If the results is a float and has only zero on the right side, normalize
if isinstance(result, float):
result = Decimal(result).normalize()
else:
result = result
# Clear entry field and insert results
self.entry.delete(0, 'end')
self.entry.insert('end', result)
# Clear the entry field
def clear(self, event=None):
self.entry.delete(0, 'end')
self.entry.insert('end', '0')
Window().mainloop()
Last edited: