Tiny Tkinter Calculator (Python)

Updated vegaseat 5 Tallied Votes 10K Views Share

Just a relatively simple calculator using the Tkinter GUI. It has a few nice features such as correcting division by an integer (for older Python versions), error trapping, to and from memory buttons, and an editable display. The editable display allows you to backspace mistakes, and also to enter things not on the key pad, like hexnumbers. For instance if you enter 0xFF and press equals, it will give you the decimal (denary) equivalent of 255

The program also has a guard against the bad guys that like to abuse the underlying eval() function to wipe out files.

I wrote the code in detail, so you can hopefully figure it out. You can fancy up the calculator quite a bit, just experiment with the code.

See also the updated version at ...
http://www.daniweb.com/software-development/python/code/467452/updated-tiny-tkinter-calculator-python

sneekula commented: nice code +12
# a tiny/simple Tkinter calculator (improved v.1.1)
# if you enter a number with a leading zero it will be an octal number!
# eg. 012 would be a decimal 10  (0.12 will not be affected)
# used a more modern import to give Tkinter items a namespace
# tested with Python24     vegaseat     08dec2006

"""
calculator has a layout like this ...
<   display   >
7  8  9  *  C
4  5  6  /  M->
1  2  3  -  ->M
0  .  =  +  neg
"""

import Tkinter as tk

def click(key):
    global memory
    if key == '=':
        # avoid division by integer
        if '/' in entry.get() and '.' not in entry.get():
            entry.insert(tk.END, ".0")
        # guard against the bad guys abusing eval()
        str1 = "-+0123456789."
        if entry.get()[0] not in str1:
            entry.insert(tk.END, "first char not in " + str1)
        # here comes the calculation part
        try:
            result = eval(entry.get())
            entry.insert(tk.END, " = " + str(result))
        except:
            entry.insert(tk.END, "--> Error!")
    elif key == 'C':
        entry.delete(0, tk.END)  # clear entry
    elif key == '->M':
        memory = entry.get()
        # extract the result
        if '=' in memory:
            ix = memory.find('=')
            memory = memory[ix+2:]
        root.title('M=' + memory)
    elif key == 'M->':
        entry.insert(tk.END, memory)
    elif key == 'neg':
        if '=' in entry.get():
            entry.delete(0, tk.END)
        try:
            if entry.get()[0] == '-':
                entry.delete(0)
            else:
                entry.insert(0, '-')
        except IndexError:
            pass
    else:
        # previous calculation has been done, clear entry
        if '=' in entry.get():
            entry.delete(0, tk.END)
        entry.insert(tk.END, key)

root = tk.Tk()
root.title("Simple Calculator")

btn_list = [
'7',  '8',  '9',  '*',  'C',
'4',  '5',  '6',  '/',  'M->',
'1',  '2',  '3',  '-',  '->M',
'0',  '.',  '=',  '+',  'neg' ]

# create all buttons with a loop
r = 1
c = 0
for b in btn_list:
    rel = 'ridge'
    cmd = lambda x=b: click(x)
    tk.Button(root,text=b,width=5,relief=rel,command=cmd).grid(row=r,column=c)
    c += 1
    if c > 4:
        c = 0
        r += 1

# use Entry widget for an editable display
entry = tk.Entry(root, width=33, bg="yellow")
entry.grid(row=0, column=0, columnspan=5)

root.mainloop()
vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

Simplified the code by creating all the buttons in a loop. Hope you can still follow the flow.

BTW, this is a tiny calculator using a small footprint and short code. You can add more features, but then it wouldn't be a tiny calculator any longer. So, go ahead and improve it and change it to a scientific calculator.

pythonNerd159 -4 Light Poster

Would you know how to do that using the Tkinter buttons? Is using self a bad thing when dealing with the buttons.


Editor's note: Sorry, put that into the wrong post!
BTW, this is a tiny calculator using a small footprint and short code. You can add more features, but then it wouldn't be a tiny calculator any longer. So, go ahead and improve it and change it to a scientific calculator.

TrustyTony 888 pyMod Team Colleague Featured Poster

Of course it could be considered user responsibility, but I do not personally like that the calculator does not allow to continue from result and saves formula to memory instead of evaluating the result automatically.

For example:
10/3 M-> = result: 3.333333
* M<- =
result: *10/3.0first char not in -+0123456789.--> Error!

1/3=*3
result: *3first char not in -+0123456789.--> Error!

alessiobat 0 Newbie Poster

how would you insert square root calculation in this program? I am trying
elif key == 'sqrt':
a = eval(entry.get())
entry.insert(tk.END, "=" + str(math.sqrt(a))
but of cours it's not working. Any ideas, please?

vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

Ah, the power of the eval() function. With this tiny calculator you can easily find the square-root as long as you remember that the square-root of x is simply x to the power 1/2.

So, to find the square-root of 2 simply enter 2**0.5=

alessiobat 0 Newbie Poster

elif key == 'sqrt':
result = math.sqrt(eval(entry.get()))
entry.insert(END,"√= "+str(result))
this is it. it works for sqrt.

amriasenthil 0 Newbie Poster
import Tkinter as tk
from Tkinter import *
import tkMessageBox
root = Tk()
buttons = {}
signVal = ''
firstVal = 1
root.title('Calculator')
root.attributes("-toolwindow", 1)

def createNumbers():
    global buttons
    buttonNum = 0

    for b in range( 2 ):
        for b2 in range( 5 ):
            button = Button(frame2, text = buttonNum, font = "Courier 9", width = 5, bd = 3 )
            button.grid(row=b, column=b2)
            buttons[ button ] = buttonNum
            buttonNum += 1
            button.bind( "<Button-1>", makeChoice )


def operators():
    button = Button(frame2, text = '+', font = "Courier 9", width = 5, bd = 3, command = lambda : operation('+') )
    button.grid(row=2, column=0)
    button = Button(frame2, text = '-', font = "Courier 9", width = 5, bd = 3, command = lambda : operation('-') )
    button.grid(row=2, column=1)
    button = Button(frame2, text = '*', font = "Courier 9", width = 5, bd = 3, command = lambda : operation('*') )
    button.grid(row=2, column=2)
    button = Button(frame2, text = '/', font = "Courier 9", width = 5, bd = 3, command = lambda : operation('/') )
    button.grid(row=2, column=3)
    button = Button(frame2, text = '=', font = "Courier 9", width = 5, bd = 3, command = lambda : excutionPart('=') )
    button.grid(row=2, column=4)
    button = Button(frame2, text = 'Clear', font = "Courier 9", width = 5, bd = 3, command = lambda : clearAll('clear') )
    button.grid(row=3, column=0)

def makeChoice( event ):
    global buttons    
    if (v.get() is None) or (len(v.get()) == 0):
       v.set(buttons[ event.widget ])       
    else:
        v.set(str(v.get())+str(buttons[ event.widget ]))

def operation(value):
    try:        
        global signVal
        global firstVal
        signVal = value
        if not isinstance(v.get(), int):
            firstVal = int(v.get())
        else:
            tkMessageBox.showerror("Error","Wrong Formate")
        print "First Value :", firstVal
        v.set('')
    except TypeError:
        tkMessageBox.showerror("Error","Wrong Formate")


def excutionPart(ex):
    print "Second Value :", str(v.get())
    if signVal is '+':
        v.set(int(firstVal)+int(v.get()))
    elif signVal is '-':
        v.set(int(firstVal)-int(v.get()))
    elif signVal is '*':
        v.set(int(firstVal)*int(v.get()))
    elif signVal is '/':
        v.set(int(firstVal)/int(v.get()))
    else:
        v.set('')
    print "Result is :", str(v.get())

def clearAll(val):
    v.set('')


#Top Frame 
frame1 = Frame(root)
frame1.pack(side = TOP)

#Bottom Frame 
frame2 = Frame(root)
frame2.pack(side = BOTTOM)

v = StringVar()
e = Entry(frame1, textvariable=v, width = 30)
e.pack(side = LEFT)



createNumbers()
operators()

root.mainloop()
Heading Here

Python Calculator Program

ZZucker 342 Practically a Master Poster

The tiny calculator is a great start of a fancier calculator. Thank you!

Kristal_1 0 Newbie Poster

If i wanted to change this so that when i click = on the calculator it displayed the result in the box like '1 + 1 = 2' how would i go about doing this?

vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

Press the buttons in this order
1 + 1 =

See also the updated version at
https://www.daniweb.com/software-development/python/code/467452/updated-tiny-tkinter-calculator-python

Kristal_1 0 Newbie Poster

is it possible to adjust something in the code so that it becomes a reverse polish notation calculator? Or does anyone know the coding for one of those?

vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

Here is a simple reverse polish calculator ...

''' calculator_reverse_polish.py
a simple calculator using a switch/case approach and lambda
'''

def do_operation(op, a, b):
    """
    arguments are in reverse polish notation order
    a dictionary combined with the lambda inline 
    function acts like C switch/case
    """
    return {'+': lambda: a + b,
            '-': lambda: a - b,
            '*': lambda: a * b,
            '/': lambda: 1.0*a / b  # Python 2 compromise
           }[op]()


print(do_operation('+', 3, 6))  # 9
print(do_operation('/', 3, 6))  # 0.5
print(do_operation('*', 3, 6))  # 18
print(do_operation('-', 3, 6))  # -3

The eval() function wouldn't like the notation.

rose anne_1 0 Newbie Poster

is it possible to have a same code of your python calculator? this is the 1st time i saw a situation like this

Charles_24 0 Newbie Poster

is it possible thatif we click on the button on the keyboard then the numbers and operators will display on the screen of the calculator ?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.