Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!
Resource icon

Simple Tkinter Calculator - Full Code

Here is the full working code
Python:
# Do the imports
import tkinter as tk
from decimal import Decimal

class Window:
    def __init__(self, parent):
        self.parent = parent
        ''' We will be using the grid manager '''
        parent.columnconfigure(0, weight=1)
        parent.rowconfigure(0, weight=1)

        # Set a minimum size for our window
        parent.geometry('800x600+200+200')
        parent.resizable(False, False)


        # Create a container to hold all the widgets.
        # We will put the container in the parent widget
        # and use sticky to pull it in all four directions.
        # We also will use the padding argument to give some padding
        # to the main container. The columnconfig and rowconfig helps
        # in keeping the buttons width and heigh the same
        container = tk.Frame(parent)
        container.grid(column=0, row=0, sticky='news', padx=8, pady=6)
        for i in range(4):
            container.grid_columnconfigure(i, weight=3, uniform='cols')
        for i in range(1, 6):
            container.grid_rowconfigure(i, weight=3, uniform='rows')

        # Create an entry widget and give it a column span of 4
        self.entry = tk.Entry(container, font=(None, 16, 'normal'), relief='sunken')
        self.entry.focus()
        self.entry.grid(column=0, columnspan=4, row=0, sticky='new', pady=5, padx=4)

        '''
            Setting up the buttons we will create an empty list and
            append the buttons as we create them. We will also set
            variables alled col, row, and index. col and index will be set to 0
            and row will be set to 1. We want our buttons to start at row 1.
            The entry field is in row 0
        '''
        # Create the items that we want our button text to be
        # The items list is setup to the order in which we build the buttons
        # by row
        items = [7,8,9,'*',5,6,7,'/',1,2,3,'+',0,'.','=','-']
        self.btns = []
        col, row, index = 0, 1, 0

        for item in items:
            size = 30 if item in ('.', '-') else 14
            self.btns.append(tk.Button(container, text=item, cursor='hand2'))
            self.btns[index]['font'] = (None, size, 'normal')
            self.btns[index].grid(column=col, row=row, sticky='news', padx=4, pady=4)
            index += 1
            
            # If we reach the 3rd column - set col = 0 and increase row + 1
            # else increase col + 1
            if col >= 3:
                col = 0
                row +=1
            else:
                col += 1

        # Create and append a clear button
        self.btns.append(tk.Button(container, text='Clear', font=(None, 14, 'normal'), cursor='hand2'))
        self.btns[16]['bg'] = 'tomato'
        self.btns[16]['activebackground'] = 'red'
        self.btns[16]['activeforeground'] = 'white'
        self.btns[16].grid(column=0, columnspan=4, sticky='news', padx=4, pady=4)


class Controller:
    ''' The Controller class will hand all button commands as well as calculations '''
    def __init__(self, window):
        self.window = window
        
        # Create commands for our buttons
        for btn in self.window.btns:
            # If the buttons are not = or clear - give the insert command
            if btn['text'] not in ['Clear', '=']:
                btn['command'] = lambda var=btn['text']: self.insert(var)
            elif btn['text'] == 'Clear':
                # If the button is the clear button - clear the field
                btn['command'] = lambda: self.clear(None)
            else:
                # Else calculate
                btn['command'] = lambda var=btn['text']: self.calculate(var)

        # Bind keys to perform some actions
        self.window.parent.bind('<Return>', lambda var=btn['text']: self.calculate(var))
        self.window.parent.bind('<KP_Enter>', lambda var=btn['text']: self.calculate(var))
        self.window.parent.bind('<Escape>', self.clear)

        # Validate input - Needs to be numbers or *,+,/,-
        valid = self.window.parent.register(self.valid_input)
        self.window.entry.configure(validate='key', validatecommand=(valid, '%S'))

    def valid_input(self,arg):
        ''' Method for validating input '''
        if arg.isalpha() or arg == '=':
            return False
        else:
            return True
 
    def clear(self, event):
        ''' Method for clearing the entry field '''
        self.window.entry.delete(0, 'end')

    def insert(self, var):
        ''' Method for inserting numbers in the entry field '''
        self.window.entry.insert('end', var)

    def calculate(self, event):
        ''' Method for doing calculations '''

        # Get the values of the entry field
        values = self.window.entry.get()

        # Do and get the calculations from the entry field using eval
        # It is reccommended not to use eval but, for our purpose
        # it will be fine
        result = eval(values)

        # Checking if our number is a float and is a whole number.
        # If it is a whole number it will remove the .0
        # else return the number as is
        if isinstance(result, float):
            result = Decimal(result).normalize()
        else:
            result = result

        # Clear the entry field and insert the calculation back into the entry field
        self.window.entry.delete(0, 'end')
        self.window.entry.insert('end', result)
        

if __name__ == '__main__':
    root = tk.Tk()
    root.title('Tkinter Calculator')
    controller = Controller(Window(root))
    root.mainloop()
Back
Top Bottom