Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
calculator app problem
#1
hello. so im trying to build a calculator app GUI with tkinter and i have the following problem
First to explain how the code works, i concatenate digits to the string representations of each of the variables. the state of a boolean variable is used to decide which of the variables to concatenate the digits to. this boolean is initially set as false and is set to true when the operator is chosen in order to append the selected digits to the second num variable. my code follows


from tkinter import *
from tkinter import messagebox
import time

#initialize the values
#uses separated boolean value to decide which number
#gets the digit appended to
first_num="";second_num="";separated=False;operator=""

#use lambda functions to generate mathematical operations
exponents = lambda num1, num2: num1 ** num2
multiplication = lambda num1, num2: num1 * num2
division = lambda num1, num2: num1 / num2
addition = lambda num1, num2: num1 + num2
subtraction = lambda num1, num2: num1 - num2

def concatenate_digit(digit):
    '''appends the chosen digit to either the first number
    or the second of the operation dependent on global boolean value
    also changes the label text to include the updated value of the variables'''
    global first_num, second_num
    if separated:
        second_num += digit
        result_lbl.config(text=f"{first_num} {operator} {second_num}")
    else:
        first_num += digit
        result_lbl.config(text=f"{first_num}")

def clear_entry():
    '''deletes last digit in the current value '''
    global first_num, second_num
    if separated:
        second_num = second_num[:-1]
    else:
        first_num = first_num[:-1]
    result_lbl.config(text=f"{first_num} {operator} {second_num}")

def clear_everything():
    global first_num, second_num, separated, operator
    first_num = ""; second_num = ""; separated = False; operator = ""
    result_lbl.config(text="")

def equals_func():
    global first_num,second_num,operator
    num1=float(first_num)
    num2=float(second_num)
    if operator=="+":
        result=addition(num1,num2)
        result_lbl.config(text=f"{first_num} {operator} {second_num} = {result}")

    elif operator=="-":
        result=subtraction(num1,num2)
        result_lbl.config(text=f"{first_num} {operator} {second_num} = {result}")

    elif operator=="^":
        result=exponents(num1,num2)
        result_lbl.config(text=f"{first_num} {operator} {second_num} = {result}")

    elif operator=="*":
        result=multiplication(num1,num2)
        result_lbl.config(text=f"{first_num} {operator} {second_num} = {result}")

    elif operator=="/":
        try:
            result=division(num1,num2)
        except ZeroDivisionError:
            messagebox.showerror(title="OOooops",message="Cannot divide by zero. Try again!!")
            clear_everything()
        else:
            result_lbl.config(text=f"{first_num} {operator} {second_num} = {result}")
    if checkbutton.get()==1:
        try:
            first_num=str(result)
        except UnboundLocalError:
            messagebox.showerror(title="OOOoooops",message=f"{first_num} is not a compatible value. Restarting")
            first_num="";second_num="";operator="";separated=False
        else:
            second_num=""
            separated=True
            result_lbl.config(text=f"{first_num}")
    else:
        first_num=""
        second_num=""
        operator=""
        separated=False


def op_set(op):
    global operator,separated
    separated=True
    operator=op


window=Tk()
window.title("Calculator App")
canvas=Canvas(window,width=600,height=600)


result_lbl=Label(text="Mathematical Operations")
result_lbl.grid(row=0,column=0,columnspan=6)
# Update button commands to use the new concatenate_digit function
Button(text="1", command=lambda: concatenate_digit("1")).grid(row=1,column=0)
two_but = Button(text="2", command=lambda: concatenate_digit("2")).grid(row=1,column=1)
three_but = Button(text="3", command=lambda: concatenate_digit("3")).grid(row=1,column=2)
four_but = Button(text="4", command=lambda: concatenate_digit("4")).grid(row=2,column=0)
five_but = Button(text="5", command=lambda: concatenate_digit("5")).grid(row=2,column=1)
six_but = Button(text="6", command=lambda: concatenate_digit("6")).grid(row=2,column=2)
seven_but = Button(text="7", command=lambda: concatenate_digit("7")).grid(row=3,column=0)
eight_but = Button(text="8", command=lambda: concatenate_digit("8")).grid(row=3,column=1)
nine_but = Button(text="9", command=lambda: concatenate_digit("9")).grid(row=3,column=2)
dot_but = Button(text=".", command=lambda: concatenate_digit(".")).grid(row=4,column=0)
zero_but = Button(text="0", command=lambda: concatenate_digit("0")).grid(row=4,column=1)
Button(text=".",command=lambda: concatenate_digit(".")).grid(row=4,column=0)
backspace_but = Button(text="<|", command=clear_entry).grid(row=4,column=2)


add_but=Button(text="+",command=lambda: op_set("+"))
add_but.grid(row=1,column=3)

sub_but=Button(text="-",command=lambda: op_set("-")).grid(row=2,column=3)
div_but=Button(text="/",command=lambda: op_set("/")).grid(row=3,column=3)
mul_but=Button(text="*",command=lambda: op_set("*")).grid(row=4,column=3)
equals_but=Button(text="=",command=equals_func).grid(row=3,column=4)
exp_but=Button(text="^",command=lambda: op_set("^")).grid(row=2,column=4)
clear_everything_but=Button(text="CE",command=clear_everything).grid(row=4,column=4)
checkbutton=IntVar()
res_check=Checkbutton(window,text="Continue with result",variable=checkbutton,onvalue=1,offvalue=0).grid(row=5,column=1)
window.mainloop()
the problem is that if i run the code it works just fine for the first calculation. when i try to concatenate digits to the first num for a second calculation then the program concatenates the digits to the second num variable instead of the first. please help. it has to be a logic bug but i cant find it. as you can see in the code i revert to the boolean variable to the initial False value when the equals function is used. I just dont know where im going wrong with this. please help
Reply
#2
The most common way I've seen is to make a tkinter calculator is use the buttons to enter an expression, and and eval() to evaluate the expression and display the result. In this type of calculator you don't worry about numbers or operators, the key presses just add a character to the expression text.
3 - 6 / 2 would be one string. Pressing "=" would call eval("3 - 6 / 2") and paste the result in the display.

If you want a calculator that works more like a regular calculator, I suggest a postfix calculator. In a postfix calculator you would enter the expression 3 - 6 / 2 as 3 6 2 / -. This calculator has no "=" button, it has an enter button that you press when you are done entering a number. To enter the equation 3 - 6 / 2 you would press 3 enter 6 enter 2 / -. The advantage of postfix is you don't have to worry about operator precedence, because equations are evaluated as soon as an operator key is pressed. The disadvantage is most people find postfix confusing. Once you get used to it, you never want to go back to infix.

An infix calculator is challenging. Your code needs to know operator precedence and perform calculations differently based on the precedence.
You will not have first_num and second_num, but instead have a stack of nums. Solving 3 - 6 / 2 requires holding on to the 3 until after you divide 6 / 2, then you can do the subtraction. If done properly, there is no need for a continue with result checkbox.

The reason your code does not reset separated = False after pressing the enter key is because the separated variable is local to the equals() function. It is not the global separated variable used in concatenate_digit(). Also, you don't assign anything to first_num or second_num in concatenate_digit(), so these don't need to be declared as global.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Calculator problem BeginnerCoderPaero 4 3,438 Jun-29-2018, 09:21 AM
Last Post: BeginnerCoderPaero
  Beginner. Calculator problem ¯\_(ツ)_/¯ stykus1992 0 2,387 Feb-15-2018, 11:01 AM
Last Post: stykus1992
  Tip calculator problem Dhaval 1 4,516 Jun-06-2017, 12:49 PM
Last Post: sparkz_alot

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020