0

I was wondering if you can help me with my Python coding if you have a chance. I am a complete noob at Python so I am trying to learn the basics for my class (and our teacher doesn't teach well at all). We are currently working on a tkinter GUI.

I am currently tasked with coding a pretty simple calculator for my class that involves with all numbers 0 - 9, square root, square root of addition of squares of two given values (sqrt(A2 + B2)), sin, cos, and tan) function as well as lastly sin-1, cos-1, and tan-1.

Now, I have completed the majority of this task as it can be seen here in the pastebin link below:

However, the only thing I can't figure out for the life of me is being able to have my "INV" button working in the sense so that when I would click the button INV, it would replace the three trig functions buttons on the calculator (sin, cos, tan) and replace it with inverse buttons(sin-1, cos-1, tan-1). Then, once I completed calculating said inverse trig function, the inverse buttons(sin-1, cos-1, tan-1) would then be replaced back again to normal trig (sin, cos, tan).

I am able to toggle between the trig and inverse trigs. However, after toggling the INV button twice, it stops calculating trig and inverse trig numbers after that (though continues to toggle just fine).

Is there any way I could make that function loop infinitely, so it calculated every time I toggle or something along the lines of that? I am very stuck lol.

from tkinter import *
import tkinter as tk
import math

expression = ""

inverted = False

def press(num):
    global expression
    expression = expression + str(num)
    equation.set(expression)


def equalpress():
    try:
        global expression
        total = eval(expression)
        equation.set(total)
        expression = str(total)

    except:
        equation.set(" Error ")
        expression = ""


def clear():
    global expression
    expression = ""
    equation.set("")
    return


def sqrt():
    global expression
    expression = math.sqrt(float(expression))
    equation.set(float(expression))
    expression = str(expression)


def sin():
    global expression
    expression = float(expression)
    expression = round(math.sin(math.radians(expression)), 5)
    equation.set(float(expression))
    expression = str(expression)


def cos():
    global expression
    expression = float(expression)
    expression = round(math.cos(math.radians(expression)), 5)
    equation.set(float(expression))
    expression = str(expression)


def tan():
    global expression
    expression = float(expression)
    expression = round(math.tan(math.radians(expression)), 5)
    equation.set(float(expression))
    expression = str(expression)


def asin():
    global expression
    expression = float(expression)
    expression = round((math.asin(expression)) * (180 / math.pi), 3)
    equation.set(float(expression))
    expression = str(expression)


def acos():
    global expression
    expression = float(expression)
    expression = round((math.acos(expression)) * (180 / math.pi), 3)
    equation.set(float(expression))
    expression = str(expression)


def atan():
    global expression
    expression = float(expression)
    expression = round((math.atan(expression)) * (180 / math.pi), 3)
    equation.set(float(expression))
    expression = str(expression)


def retrieve_input():
    try:
        global expression
        inputValue1 = InputA.get()
        inputValue2 = InputB.get()
        inputValue1 = float(inputValue1)
        inputValue2 = float(inputValue2)

        expression = float(math.sqrt(inputValue1 * inputValue1 + inputValue2 * inputValue2))
        equation.set(float(expression))
        expression = str(expression)

    except:
        equation.set(" Error ")
        expression = ""

def inv():
    global inverted
    inverted = not inverted


if __name__ == "__main__":
    gui = Tk()

    gui.configure(background="light blue")

    gui.title("Calculator")

    gui.geometry("500x220")

    equation = StringVar()
    A = StringVar()
    B = StringVar()

    expression_field = Entry(gui, textvariable=equation)

    expression_field.grid(columnspan=45, ipadx=200)

    equation.set('Enter Your Expression')

    lbl1 = Label(gui, text="Enter A value:", font=("Arial Bold", 10),
    bg="light blue")
    lbl1.grid(column=0, row=13, sticky=W)
    InputA = Entry(gui, width=12, textvariable=A)
    InputA.grid(column=1, row=13)

    lbl2 = Label(gui, text="Enter B value:", font=("Arial Bold", 10),
    bg="light blue")
    lbl2.grid(column=0, row=14, sticky=W)
    InputB = Entry(gui, width=12, textvariable=B)
    InputB.grid(column=1, row=14)

    buttonab = Button(gui, text=' √(A^2 + B^2) ', fg='black', bg='white',
    command=lambda: retrieve_input(), height=1,width=11)
    buttonab.grid(row=15, column=0, sticky=W + E)

    button1 = Button(gui, text=' 1 ', fg='black', bg='pink',
    command=lambda: press(1), height=1, width=7)
    button1.grid(row=4, column=0)

    button2 = Button(gui, text=' 2 ', fg='black', bg='pink',
    command=lambda: press(2), height=1, width=7)
    button2.grid(row=4, column=1)

    button3 = Button(gui, text=' 3 ', fg='black', bg='pink',
    command=lambda:
    press(3), height=1, width=7)
    button3.grid(row=4, column=2)

    button4 = Button(gui, text=' 4 ', fg='black', bg='pink',
    command=lambda: press(4), height=1, width=7)
    button4.grid(row=3, column=0)

    button5 = Button(gui, text=' 5 ', fg='black', bg='pink',
    command=lambda: press(5), height=1, width=7)
    button5.grid(row=3, column=1)

    button6 = Button(gui, text=' 6 ', fg='black', bg='pink',
    command=lambda: press(6), height=1, width=7)
    button6.grid(row=3, column=2)

    button7 = Button(gui, text=' 7 ', fg='black', bg='pink',
    command=lambda: press(7), height=1, width=7)
    button7.grid(row=2, column=0)

    button8 = Button(gui, text=' 8 ', fg='black', bg='pink',
    command=lambda: press(8), height=1, width=7)
    button8.grid(row=2, column=1)

    button9 = Button(gui, text=' 9 ', fg='black', bg='pink',
    command=lambda: press(9), height=1, width=7)
    button9.grid(row=2, column=2)

    button0 = Button(gui, text=' 0 ', fg='black', bg='pink',
    command=lambda: press(0), height=1, width=7)
    button0.grid(row=5, column=1)

    plus = Button(gui, text=' + ', fg='black', bg='yellow',
    command=lambda: press("+"), height=1, width=7)
    plus.grid(row=2, column=3)

    minus = Button(gui, text=' - ', fg='black', bg='yellow',
    command=lambda:
    press("-"), height=1, width=7)
    minus.grid(row=3, column=3)

    multiply = Button(gui, text=' * ', fg='black', bg='yellow',
    command=lambda: press("*"), height=1, width=7)
    multiply.grid(row=4, column=3)

    divide = Button(gui, text=' / ', fg='black', bg='yellow',
    command=lambda: press("/"), height=1, width=7)
    divide.grid(row=5, column=3)

    equal = Button(gui, text=' = ', fg='black', bg='red',
    command=equalpress, height=1, width=7)
    equal.grid(row=5, column=2)

    clear = Button(gui, text='Clear', fg='black', bg='red', command=clear,
    height=1, width=7)
    clear.grid(row=2, column=6)

    sqrt = Button(gui, text=' √ ', fg='black', bg='yellow', command=sqrt,
    height=1, width=7)
    sqrt.grid(row=3, column=6)

    dec = Button(gui, text=' . ', fg='black', bg='orange', command=lambda:
    press("."), height=1, width=7)
    dec.grid(row=5, column=0)

    sin = Button(gui, text='sin', fg='black', bg='light green',
    command=sin, height=1, width=7)
    sin.grid(row=2, column=4)

    cos = Button(gui, text='cos', fg='black', bg='light green',
    command=cos, height=1, width=7)
    cos.grid(row=3, column=4)

    tan = Button(gui, text='tan', fg='black', bg='light green',
    command=tan, height=1, width=7)
    tan.grid(row=4, column=4)

    inv = Button(gui, text='INV', fg='black', bg='light green',
    command=inv, height=1, width=7)
    inv.grid(row=6, column=4)

    if not inverted:
        sin = Button(gui, text='sin', fg='black', bg='light green', 
        command=sin, 
        height=1, width=7)
        sin.grid(row=2, column=4)

        cos = Button(gui, text='cos', fg='black', bg='light green', 
        command=cos, 
        height=1, width=7)
        cos.grid(row=3, column=4)

        tan = Button(gui, text='tan', fg='black', bg='light green', 
        command=tan, 
        height=1, width=7)
        tan.grid(row=4, column=4)

    else:
        sin = Button(gui, text='sin^-1', fg='black', bg='light green', 
        command=asin, height=1, width=7)
        sin.grid(row=2, column=4)

        cos = Button(gui, text='cos-1', fg='black', bg='light green', 
        command=acos, height=1, width=7)
        cos.grid(row=3, column=4)

        tan = Button(gui, text='tan-1', fg='black', bg='light green', 
        command=atan, height=1, width=7)
        tan.grid(row=4, column=4)

gui.mainloop()

1 Answers1

0

you have a little bit of work to do.

Currently, when you click your INV-Button youre replacing your "sin" Button with a "global sin" Button. There is no Crash but TK isnt working properly anymore and struggles with the command parameter. I suggest you create a guiloop which handles all your button designs which is permanently running in the _main_loop.

Then you need to change your Inv-function just to

def inv():
    global inverted
    inverted = not inverted

after that design your gui-loop like this:

if not inverted:
   sin = Button(gui, text='sin', fg='black', bg='light green', command=sin, height=1, width=7)
        sin.grid(row=2, column=4)
    else:
        sin = Button(gui, text='sin^-1', fg='black', bg='light green', command=asin, height=1, width=7)
        sin.grid(row=2, column=4)

I just tried it with one button and it worked.

For further gui-programming i recommend using PyQT5. Even it's first not very intuitive i find this more stable and powerful.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Eirik Fesker
  • 328
  • 1
  • 12
  • Thanks for the response. Just tried to implement with what you were saying, changing my inv() function to yours. I also put the guiloop if-else statement you wrote within my main loop but for all three buttons. Though, I do not know why I am getting the error: "NameError: name 'inverted' is not defined". – Matias Salgo Sep 21 '19 at 22:17
  • dont forget to define it at the beginning of your file. `(inverted = False)` – Eirik Fesker Sep 21 '19 at 22:25
  • Yea, just did that and the error went away! Only thing is, when I click the INV button now it doesn't toggle to the corresponding inverse functions for some reason. I can only calculate sin cos tan. Sorry for so many question since I am very new to this. Appreciate helping me – Matias Salgo Sep 21 '19 at 22:35
  • By the way, I have edited my code in my post to show what I have done thus far from what you said. – Matias Salgo Sep 22 '19 at 00:51
  • Yes that happens, because TK doesn't refresh automatically. You need to create a refresh function like "tk.update()". And you should create a class like `class window(tk.frame)` which is created in the main loop. then you can call every button inside that class via `self`function. Your actual code doesn't allow your buttons to get changed by outside mainloop functions. So you need inner-class functions :) But this isnt explained in a comment. I think this thread in SO could guide you further: https://stackoverflow.com/questions/19477636/does-tkinter-have-a-refresh-method – Eirik Fesker Sep 22 '19 at 10:28
  • Awesome I will check it out then! – Matias Salgo Sep 22 '19 at 19:08