'Python Tkinter GUI Calculator

So I am currently in the process of making a GUI Calculator, but am unsure on how to write code that will perform the operations of the calculator. Right now I currently have setup the window, entry box, and calculator buttons, but none of them actually do anything at the moment.

I am just confused on how these buttons are represented in code and so I am not sure how to write a block of code that will be able to read in these button inputs and perform addition,subtraction, etc.

Here is my code so far

class Calculator(Frame):
def __init__(self,master):
    Frame.__init__(self,master)
    self.grid()

    self.dataEnt = Entry(self)
    self.dataEnt.grid(row = 0, column = 1, columnspan = 4)

    labels =[['AC','%','/'],
         ['7','8','9','*'],
         ['4','5','6','-'],
         ['1','2','3','+'],
         ['0','.','=']]
    label = Button(self,relief = RAISED, padx = 10, text = labels[0][0]) #AC
    label.grid(row = 1, column = 0, columnspan = 2)
    label = Button(self,relief = RAISED, padx = 10, text = labels[0][1]) # %
    label.grid(row = 1, column = 3)
    label = Button(self,relief = RAISED, padx = 10, text = labels[0][2]) # /
    label.grid(row = 1, column = 4)
    for r in range(1,4):
        for c in range(4):
            #create label for row r and column c 
            label = Button(self,relief = RAISED,
                          padx = 10,
                          text = labels[r][c]) # 789* 456- 123+ 
            # place label in row r and column c
            label.grid(row = r+1, column = c+1)

    label = Button(self,relief = RAISED, padx = 10, text = labels[4][0]) #0
    label.grid(row = 5, column = 0, columnspan = 2)
    label = Button(self,relief = RAISED, padx = 10, text = labels[4][1]) # .
    label.grid(row = 5, column = 3)
    label = Button(self,relief = RAISED, padx = 10, text = labels[4][2]) # =
    label.grid(row = 5, column = 4)

  def operations(self,num ):

def main():
    root = Tk()
    root.title('Calculator')
    obj = Calculator(root)
    root.mainloop()            

and here is what the calculator looks like so far

My guess is that I need to somehow be able to read the input as a string and then have python evaluate that string as a mathematical expression but I am not sure how to go about it.

Thanks for any help!



Solution 1:[1]

What you could do is bind all buttons to a method that identifies the button and append a string to a list or evaluate the expression. This list could then be displayed in the label.

def button_press(self, event):
    widget = event.widget
    text = widget["text"]
    if text != "AC" and text != "=":
        self.operations.append(text)
    elif text == "AC":
        self.operations = []  # Clear the list.
    elif text == "=":
        self.evaluate()
    self.label["text"] = "".join(self.operations)

def evaluate(self):
    try:
        self.operations = [str(eval("".join(self.operations)))]
    except (ArithmeticError, SyntaxError, TypeError, NameError):
        self.operations = ["ERROR"]

This code cannot just be pasted in to your program, it's just to demonstrate how you could solve the problem.

Solution 2:[2]

use simply pyautogui for basic GUI calculator

import math
import pyautogui
print( '+ =add |- =subtraction |* =multiplication | / =division |w =remainder of division |i =percentage |s =product of a number by itself \n'
        '|p =prime number |r =square root')
def p(num):
    for i in range(2, int(num)):
        if int(num) % i == 0:
            return i
    return False
while True:
    try:
        try:
            #----------------------------------------------------------#
            num=float(pyautogui.prompt('1st','pcalculator'))
            op=pyautogui.prompt('sign','pcalculator')
            if not op == 'p':
                nun=float(pyautogui.prompt('2nd','pcalculator'))
            if op=='+':
            x=pyautogui.confirm(num+nun,'pcalculator ',buttons=['Ok','Cancel'])
            if x=='Cancel':
                break
            elif op=='-':
                x=pyautogui.confirm(num-nun,'pcalculator ',buttons=['Ok','Cancel'])
                if x=='Cancel':
                break
            elif op=='*':
                x=pyautogui.confirm(num*nun,'pcalculator ',buttons=['Ok','Cancel'])
                if x=='Cancel':
                break
            elif op=='/':
                x=pyautogui.confirm(num/nun,'pcalculator ',buttons=['Ok','Cancel'])
                if x=='Cancel':
                break
            elif op=='w':
                x=pyautogui.confirm(num%nun,'pcalculator ',buttons=['Ok','Cancel'])
                if x=='Cancel':
                break
            elif op=='i':
                x=pyautogui.confirm(num/nun*100,'pcalculator ',buttons=['Ok','Cancel'])
                if x=='Cancel':
                break
            elif op=='s':
                x=pyautogui.confirm(num**nun,'pcalculator ',buttons=['Ok','Cancel'])
                if x=='Cancel':
                break            
            elif op=='p':
                if p(num):
                    x=pyautogui.confirm((int(num),'is a composite number'),'pcalculator',buttons=['Ok','Cancel'])
                    if x=='Cancel':
                        break
                else:
                    x=pyautogui.confirm((int(num),'is a prime number'),'pcalculator ',buttons=['Ok','Cancel'])
                    if x=='Cancel':
                        break
            elif op=='r':
                x=pyautogui.confirm(math.sqrt(num),'pcalculator ',buttons=['Ok','Cancel'])
                if x=='Cancel':
                    break
    #-------------------------------------------------------------------#
        except ZeroDivisionError:
                x=pyautogui.confirm("Error: you can not divide by 0",'pcalculator ',buttons=['Ok','Cancel'])
                if x=='Cancel':
                    break
    except ValueError:
        x=pyautogui.confirm('Invalid input,use only integers,decimals and symbols.','pcalculator ',buttons=['Ok','Cancel'])
        if x=='Cancel':
            break

Solution 3:[3]

Python Tkinter GUI Calculator without build in eval function

from tkinter import *
from tkinter import ttk

class SimpleCalculator (Tk):

    def __init__(self):
        super().__init__()

        frame = ttk.Frame(self)
        frame.grid(row=0, column=0, pady=(5, 5), padx=(5, 5))
        self.entry_screen_value = StringVar()
        self.screen_entry = ttk.Entry(frame, textvariable=self.entry_screen_value)
        self.screen_entry.grid(row=0, column=0, columnspan=4, sticky=(W, E), pady=(5, 5))

        # btn_square = ttk.Button(frame, text = "?x", command = press_square)
        # btn_square.grid(row = 1, column = 0)

        btn_delete = ttk.Button(frame, text="  C  ", command = self.press_delete)
        btn_delete.grid(row=2, column=3)

        btn_9 = ttk.Button(frame, text="  9  ", command= self.press_nine)
        btn_9.grid(row=2, column=2)

        btn_8 = ttk.Button(frame, text="  8  ", command= self.press_eight)
        btn_8.grid(row=2, column=1)

        btn_7 = ttk.Button(frame, text="  7  ", command= self.press_seven)
        btn_7.grid(row=2, column=0)

        btn_add = ttk.Button(frame, text="  +  ", command=self.press_add)
        btn_add.grid(row=3, column=3)

        btn_6 = ttk.Button(frame, text="  6  ", command=self.press_six)
        btn_6.grid(row=3, column=2)

        btn_5 = ttk.Button(frame, text="  5  ", command=self.press_five)
        btn_5.grid(row=3, column=1)

        btn_4 = ttk.Button(frame, text="  4  ", command=self.press_four)
        btn_4.grid(row=3, column=0)

        btn_sub = ttk.Button(frame, text="  -  ", command=self.press_sub)
        btn_sub.grid(row=4, column=3)

        btn_3 = ttk.Button(frame, text="  3  ", command=self.press_three)
        btn_3.grid(row=4, column=2)

        btn_2 = ttk.Button(frame, text="  2  ", command=self.press_two)
        btn_2.grid(row=4, column=1)

        btn_1 = ttk.Button(frame, text="  1  ", command=self.press_one)
        btn_1.grid(row=4, column=0)

        btn_multi = ttk.Button(frame, text="  *  ", command=self.press_multi)
        btn_multi.grid(row=5, column=3)

        btn_0 = ttk.Button(frame, text="  0  ", command=self.press_zero)
        btn_0.grid(row=5, column=0, columnspan=2, sticky=(W, E))

        btn_dot = ttk.Button(frame, text="  .  ", command=self.press_dot)
        btn_dot.grid(row=5, column=2)

        btn_divide = ttk.Button(frame, text="  ÷  ", command=self.press_divide)
        btn_divide.grid(row=6, column=3)

        btn_equal = ttk.Button(frame, text="  =  ", command=self.Press_equal)
        btn_equal.grid(row=6, column=0, columnspan=3, sticky=(W, E))


        self.mainloop()

    def press_zero(self):
        self.screen_entry.insert(END, "0")

    def press_one(self):
        self.screen_entry.insert(END, "1")

    def press_two(self):
        self.screen_entry.insert(END, "2")

    def press_three(self):
        self.screen_entry.insert(END, "3")

    def press_four(self):
        self.screen_entry.insert(END, "4")

    def press_five(self):
        self.screen_entry.insert(END, "5")

    def press_six(self):
        self.screen_entry.insert(END, "6")

    def press_seven(self):
        self.screen_entry.insert(END, "7")

    def press_eight(self):
        self.screen_entry.insert(END, "8")

    def press_nine(self):
        self.screen_entry.insert(END, "9")

    def press_dot(self):
        self.screen_entry.insert(END, ".")

    def press_delete(self):
        val = self.entry_screen_value.get()[:-1]
        self.screen_entry.delete(0, END)
        self.screen_entry.insert(END, val)

    def press_add(self):
        self.screen_entry.insert(END, "+")

    def press_sub(self):
        self.screen_entry.insert(END, "-")

    def press_multi(self):
        self.screen_entry.insert(END, "*")

    def press_divide(self):
        self.screen_entry.insert(END, "÷")

    def press_square(self):
        self.screen_entry.insert(END, "?(")
        

    def Press_equal(self):
        formula = self.doMultiFirst(self.do_divide_first(self.convertTo(self.entry_screen_value.get())))

        result = 0
        temp = 0
        sign = ""
        if len(formula) == 1:
            result = formula[0]
        else:
            for di in formula:
                if di != "+" and di != "*" and di != "-" and di != "÷":
                    if sign == "+":
                        temp = float(di)
                        result += temp
                    elif sign == "-":
                        temp = float(di)
                        result -= temp
                    elif sign == "*":
                        temp = int(di)
                        result *= temp
                    elif sign == "÷":
                        temp = float(di)
                        result /= temp
                    else:
                        temp = float(di)
                        result = temp
                else:
                    if di == "+":
                        sign = "+"
                    elif di == "-":
                        sign = "-"
                    elif di == "*":
                        sign = "*"
                    elif di == "÷":
                        sign = "÷"

        self.screen_entry.delete(0, END)
        r = str(result).split(".")[-1:]
        if r[0] == '0':
            self.screen_entry.insert(END, int(result))
        else:
            self.screen_entry.insert(END, result)

        print(formula)

    # this function convert formula = "-1+11+3+5*5" to ['-1','+','11','+','3','+','5','*','5']
    def convertTo(self, nm):
        # this temp list we store our formula in it
        dd = []
        temp = ""
        for i in range(len(nm)):

            if nm[i] != "+" and nm[i] != "*" and nm[i] != "÷" and nm[i] != "-":
                temp += nm[i]

            else:
                # if our first input is -1 we need to combine it we second input and ill be like -1
                if i == 0 and nm[0] == "-":
                    temp = "-"
                else:
                    # we add prev combination like 11 to the list after we reach sign + or * or ..
                    dd += [temp]
                    dd += [nm[i]]
                    temp = ""

            if i == len(nm) - 1:
                dd += [temp]
        return dd

    # this function convert ['3','+','4','*','2','+','3'] to ['3','+','8','+','3']
    def doMultiFirst(self, ls):
        newlist = []
        for i in range(len(ls)):

            if ls[i] == "*":
                f = float(ls[i - 1])
                l = float(ls[i + 1])
                r = f * l
                ls[i + 1] = r
                ls[i] = 0
                ls[i - 1] = 0

        for k in ls:
            if k != 0:
                newlist += [k]
        return newlist

    # this function convert ['3','+','4','÷','2','+','3'] to ['3','+','2','+','3']
    def do_divide_first(self, ls):
        newlist = []
        for i in range(len(ls)):

            if ls[i] == "÷":
                f = float(ls[i - 1])
                l = float(ls[i + 1])
                r = f / l
                ls[i + 1] = r
                ls[i] = 0
                ls[i - 1] = 0

        for k in ls:
            if k != 0:
                newlist += [k]

        return newlist



if __name__ == "__main__":

    SimpleCalculator()
   

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ted Klein Bergman
Solution 2 Aditya Kumar
Solution 3