Updated Tiny Tkinter Calculator (Python)

vegaseat 4 Tallied Votes 2K Views Share

This is the updated version of the Tiny Tkinter Calculator. It has more power, since you can type in functions contained in the Python math module then press the equals key. You can then move the result into memory for other calculations. The code is written in OOP class style as an exercise, still simple and hopefully very readable. Again, you are welcome to improve the functionality, but don't turn it into a HUGE calculator.

''' tk_calculator_tiny2.py
A updated tiny calculator using the Tkinter GUI toolkit
you can type in functions contained in module math
for instance type in  tan(pi/180)  then click  =
tested with Python27 and Python33  by  vegaseat  13nov2013

# avoid integer division by Python2
from __future__ import division
from math import *
from functools import partial
    # Python2
    import Tkinter as tk
except ImportError:
    # Python3
    import tkinter as tk

class MyApp(tk.Tk):
    def __init__(self):
        # the root will be self
        self.title("Tiny TK Calculator")
        # use width x height + x_offset + y_offset (no spaces!)
        # or set x, y position only
        self.memory = 0

    def create_widgets(self):
        # this also shows the calculator's button layout
        btn_list = [
        '7',  '8',  '9',  '*',  'C',
        '4',  '5',  '6',  '/',  'M->',
        '1',  '2',  '3',  '-',  '->M',
        '0',  '.',  '=',  '+',  'neg' ]

        rel = 'ridge'
        # create all buttons with a loop
        r = 1
        c = 0
        for b in btn_list:
            # partial takes care of function and argument
            cmd = partial(self.calculate, b)
            tk.Button(self, text=b, width=5, relief=rel,
                command=cmd).grid(row=r, column=c)
            c += 1
            if c > 4:
                c = 0
                r += 1
        # use an Entry widget for an editable display
        self.entry = tk.Entry(self, width=33, bg="yellow")
        self.entry.grid(row=0, column=0, columnspan=5)

    def calculate(self, key):
        if key == '=':
            # guard against the bad guys abusing eval()
            if '_' in self.entry.get():
                self.entry.insert(tk.END, " not accepted!")
            # here comes the calculation part
                result = eval(self.entry.get())
                self.entry.insert(tk.END, " = " + str(result))
                self.entry.insert(tk.END, "--> Error!")
        elif key == 'C':
            self.entry.delete(0, tk.END)  # clear entry
        elif key == '->M':
            self.memory = self.entry.get()
            # extract the result
            if '=' in self.memory:
                ix = self.memory.find('=')
                self.memory = self.memory[ix+2:]
            self.title('M=' + self.memory)
        elif key == 'M->':
            if self.memory:
               self.entry.insert(tk.END, self.memory)
        elif key == 'neg':
            if '=' in self.entry.get():
                self.entry.delete(0, tk.END)
                if self.entry.get()[0] == '-':
                    self.entry.insert(0, '-')
            except IndexError:
            # previous calculation has been done, clear entry
            if '=' in self.entry.get():
                self.entry.delete(0, tk.END)
            self.entry.insert(tk.END, key)

app = MyApp()
Assembly Guy 72 Posting Whiz

In this specific case, is there any advantage of using

app = MyApp()

over simply using

sneekula 969 Nearly a Posting Maven

I think it's just style.

vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

I used the app instance for some testing.

MyApp().mainloop() is simpler, thanks for reminding me.

vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

Just a reminder, please test your snippets before you submit them.

BustACode 15 Light Poster

Very nice. Thanks. I would, will, add a reciprocal key.

vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

A reciprocal key sounds like a good idea.

Remember that most of the scientific functions can simply be typed in.

For instance the squareroot of 2 ...
type in sqrt(2) then click the = button

The cube root of 10 ...
type 10**(1/3) then click the = button

Area of a circle with radius 5 ...
type in pi*5**2 then click the = button

DragonMastur 23 Light Poster

Nice. I like the way you used a loop to make the widgets and place them I never thought of that.

vegaseat 1,735 DaniWeb's Hypocrite Team Colleague

Any time you see a lot of rather repetitive code, a loop or a function comes to mind!

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.