text = ""
e = Text(window, width = 15, height = 2, font = ("Times New Roman", 24))
e.grid(column = 0, row = 0, columnspan=5)
def show_value(val): # Displays the text when user clicks buttons
global text
text =str(val)
e.insert(END, val)
def clear(): # Clears what's inside the text frame
global text
e.delete("1.0", "end")
text = ""
def delete(): # Deletes the last value/character
e.delete("end-2c")
def equal(): # Computes
global text
try:
text = str(eval(text))
e.delete("1.0", "end")
e.insert("1.0", text)
except:
clear()
e.insert("1.0", "Error")
#Buttons
# button_negative = Button(window, text = " /-", width = 6, font = ("Arial", 10)) # ADD THIS SOON
button_zero = Button(window, text = "0", width = 6, font = ("Arial", 10), bg = "black", fg = "white", command = lambda: show_value(0))
button_one = Button(window, text = "1", width = 6, font = ("Arial", 10), bg = "black", fg = "white", command = lambda: show_value(1))
button_two = Button(window, text = "2", width = 6, font = ("Arial", 10), bg = "black", fg = "white", command = lambda: show_value(2))
button_three = Button(window, text = "3", width = 6, font = ("Arial", 10), bg = "black", fg = "white", command = lambda: show_value(3))
button_four = Button(window, text = "4", width = 6, font = ("Arial", 10), bg = "black", fg = "white", command = lambda: show_value(4))
button_five = Button(window, text = "5", width = 6, font = ("Arial", 10), bg = "black", fg = "white", command = lambda: show_value(5))
button_six = Button(window, text = "6", width = 6, font = ("Arial", 10), bg = "black", fg = "white", command = lambda: show_value(6))
button_seven = Button(window, text = "7", width = 6, font = ("Arial", 10), bg = "black", fg = "white", command = lambda: show_value(7))
button_eight = Button(window, text = "8", width = 6, font = ("Arial", 10), bg = "black", fg = "white", command = lambda: show_value(8))
button_nine = Button(window, text = "9", width = 6, font = ("Arial", 10), bg = "black", fg = "white", command = lambda: show_value(9))
button_equals = Button(window, text = "=", width = 6, font = ("Arial", 10), bg = "#7C3D00", fg = "white", command = equal)
button_decimal = Button(window, text = ".", width = 6, font = ("Arial", 10), bg = "black", fg = "white", command = lambda: show_value("."))
button_add = Button(window, text = " ", width = 6, font = ("Arial", 10), bg = "black", fg = "white", command = lambda: show_value(" "))
button_subtract = Button(window, text = "-", width = 6, font = ("Arial", 10), bg = "black", fg = "white", command = lambda: show_value("-"))
button_divide = Button(window, text = "/", width = 6, font = ("Arial", 10), bg = "black", fg = "white", command = lambda: show_value("/"))
button_multiply = Button(window, text = "*", width = 6, font = ("Arial", 10), bg = "black", fg = "white", command = lambda: show_value("*"))
button_clear = Button(window, text = "AC", width = 6, font = ("Arial", 10), bg = "black", fg = "white", command = clear)
button_delete = Button(window, text = "DEL", width = 6, font = ("Arial", 10), bg = "black", fg = "white", command = delete)
button_left_bracket = Button(window, text = "(", width = 6, font = ("Arial", 10), bg = "black", fg = "white", command = lambda: show_value("("))
button_right_bracket = Button(window, text = ")", width = 6, font = ("Arial", 10), bg = "black", fg = "white", command = lambda: show_value(")"))
#button_negative.grid(row = 7, column = 0)
button_zero.grid(row = 7, column = 0)
button_decimal.grid(row = 7, column = 1)
button_equals.grid(row = 7, column = 3)
button_delete.grid(row = 7, column = 2)
button_one.grid(row = 5, column = 0)
button_two.grid(row = 5, column = 1)
button_three.grid(row = 5, column = 2)
button_add.grid(row = 5, column = 3)
button_four.grid(row = 4, column = 0)
button_five.grid(row = 4, column = 1)
button_six.grid(row = 4, column = 2)
button_subtract.grid(row = 4, column = 3)
button_seven.grid(row = 3, column = 0)
button_eight.grid(row = 3, column = 1)
button_nine.grid(row = 3, column = 2)
button_multiply.grid(row = 3, column = 3)
button_clear.grid(row = 2, column = 0)
button_left_bracket.grid(row = 2, column = 1)
button_right_bracket.grid(row = 2, column = 2)
button_divide.grid(row = 2, column = 3)
window.mainloop()
I'm still learning Python and wanted to create a Calculator as my first project. My issue is, when the user wants to compute 8 8 and clicks on the equals button, it displays 16. However, I want it to be cleared without pressing the all clear button when the user wants to calculate something new e.g 56 6 and displays that instead. How would I go about doing this?
CodePudding user response:
When manipulating GUI like tkinter, I recommend you to use Python classes, as it will be easier to manipulate elements.
As for your problem, does something like this suits your needs ?
#!/usr/bin/python3
import tkinter as tk
text = ""
CALCUL_DONE=False
window=tk.Tk()
e = tk.Text(window, width = 15, height = 2, font = ("Times New Roman", 24))
e.grid(column = 0, row = 0, columnspan=5)
def clear(): # Clears what's inside the text frame
global text
e.delete("1.0", "end")
text = ""
def show_value(val): # Displays the text when user clicks buttons
global text, CALCUL_DONE
if CALCUL_DONE:
clear()
CALCUL_DONE=False
text =str(val)
e.insert(tk.END, val)
def delete(): # Deletes the last value/character
e.delete("end-2c")
def equal(): # Computes
global text, CALCUL_DONE
try:
text = str(eval(text))
e.delete("1.0", "end")
e.insert("1.0", text)
CALCUL_DONE=True
except:
clear()
e.insert("1.0", "Error")
#Buttons
# button_negative = tk.Button(window, text = " /-", width = 6, font = ("Arial", 10)) # ADD THIS SOON
button_zero = tk.Button(window, text = "0", width = 6, font = ("Arial", 10), bg = "black", fg = "white", command = lambda: show_value(0))
[...]
button_right_bracket = tk.Button(window, text = ")", width = 6, font = ("Arial", 10), bg = "black", fg = "white", command = lambda: show_value(")"))
#button_negative.grid(row = 7, column = 0)
button_zero.grid(row = 7, column = 0)
[...]
button_divide.grid(row = 2, column = 3)
window.mainloop()
I added a boolean (CALCUL_DONE) initialized at False, so when you click on " ","-",... it changes its value to True, and when clicking on a number again, the funtion clear() is called.
CodePudding user response:
@sramazoth answer is the right basic idea, but unfortunately the way your code is written it won't work if the user is using the keyboard to enter values (and not just the displayed calculator's buttons). The problem is due to the use of that global text
variable being used. Your attempt to make make its contents the same be the same as what is in the Text
only works for clicking on the Button
s being displayed, but it's also possible for a user to directly enter values into the Text
widget via the keyboard, which will not be detect by your code.
I corrected the issue by doing two things (in addition to adding a global
flag like @sramazoth suggested):
- Eliminating the
global text
string variable completely — there's really no need for it since the text you need us already being stored in theText
widget itself. - Added a keypress event handler and bound it to the
Text
widget which will set the global flag just like clicking on one of the buttons to enter a value would.
You also need to understand that applying eval()
to untrusted user input is a severe security hazard because they can enter arbitrary code that can do bad things.
Given that caveat, here's the modified code:
import tkinter as tk
from tkinter.constants import *
clear_flag = False # Indicates when Text widget should be cleared.
window = tk.Tk()
e = tk.Text(window, width=15, height=2, font=("Times New Roman", 24))
e.grid(column=0, row=0, columnspan=5)
def on_keypress(event):
global clear_flag
if clear_flag:
clear()
clear_flag = False
e.bind('<KeyPress>', on_keypress)
def show_value(val): # Displays the expression when user clicks buttons
global clear_flag
if clear_flag:
clear()
clear_flag = False
e.insert(END, val)
def clear(): # Clears what's inside the expression frame
e.delete("1.0", "end")
def delete(): # Deletes the last value/character
e.delete("end-2c")
def equal(): # Computes
global clear_flag
try:
result = eval(e.get("1.0", END))
e.delete("1.0", "end")
e.insert("1.0", result)
except Exception as exc:
clear()
e.insert("1.0", "Error")
clear_flag = True
#Buttons
# button_negative = tk.Button(window, text=" /-", width=6, font=("Arial", 10)) # ADD THIS SOON
button_zero = tk.Button(window, text="0", width=6, font=("Arial", 10), bg="black", fg="white", command=lambda: show_value(0))
button_one = tk.Button(window, text="1", width=6, font=("Arial", 10), bg="black", fg="white", command=lambda: show_value(1))
button_two = tk.Button(window, text="2", width=6, font=("Arial", 10), bg="black", fg="white", command=lambda: show_value(2))
button_three = tk.Button(window, text="3", width=6, font=("Arial", 10), bg="black", fg="white", command=lambda: show_value(3))
button_four = tk.Button(window, text="4", width=6, font=("Arial", 10), bg="black", fg="white", command=lambda: show_value(4))
button_five = tk.Button(window, text="5", width=6, font=("Arial", 10), bg="black", fg="white", command=lambda: show_value(5))
button_six = tk.Button(window, text="6", width=6, font=("Arial", 10), bg="black", fg="white", command=lambda: show_value(6))
button_seven = tk.Button(window, text="7", width=6, font=("Arial", 10), bg="black", fg="white", command=lambda: show_value(7))
button_eight = tk.Button(window, text="8", width=6, font=("Arial", 10), bg="black", fg="white", command=lambda: show_value(8))
button_nine = tk.Button(window, text="9", width=6, font=("Arial", 10), bg="black", fg="white", command=lambda: show_value(9))
button_equals = tk.Button(window, text="=", width=6, font=("Arial", 10), bg="#7C3D00", fg="white", command=equal)
button_decimal = tk.Button(window, text=".", width=6, font=("Arial", 10), bg="black", fg="white", command=lambda: show_value("."))
button_add = tk.Button(window, text=" ", width=6, font=("Arial", 10), bg="black", fg="white", command=lambda: show_value(" "))
button_subtract = tk.Button(window, text="-", width=6, font=("Arial", 10), bg="black", fg="white", command=lambda: show_value("-"))
button_divide = tk.Button(window, text="/", width=6, font=("Arial", 10), bg="black", fg="white", command=lambda: show_value("/"))
button_multiply = tk.Button(window, text="*", width=6, font=("Arial", 10), bg="black", fg="white", command=lambda: show_value("*"))
button_clear = tk.Button(window, text="AC", width=6, font=("Arial", 10), bg="black", fg="white", command=clear)
button_delete = tk.Button(window, text="DEL", width=6, font=("Arial", 10), bg="black", fg="white", command=delete)
button_left_bracket = tk.Button(window, text="(", width=6, font=("Arial", 10), bg="black", fg="white", command=lambda: show_value("("))
button_right_bracket=tk.Button(window, text=")", width=6, font=("Arial", 10), bg="black", fg="white", command=lambda: show_value(")"))
#button_negative.grid(row = 7, column = 0)
button_zero.grid(row = 7, column = 0)
button_decimal.grid(row = 7, column = 1)
button_equals.grid(row = 7, column = 3)
button_delete.grid(row = 7, column = 2)
button_one.grid(row = 5, column = 0)
button_two.grid(row = 5, column = 1)
button_three.grid(row = 5, column = 2)
button_add.grid(row = 5, column = 3)
button_four.grid(row = 4, column = 0)
button_five.grid(row = 4, column = 1)
button_six.grid(row = 4, column = 2)
button_subtract.grid(row = 4, column = 3)
button_seven.grid(row = 3, column = 0)
button_eight.grid(row = 3, column = 1)
button_nine.grid(row = 3, column = 2)
button_multiply.grid(row = 3, column = 3)
button_clear.grid(row = 2, column = 0)
button_left_bracket.grid(row = 2, column = 1)
button_right_bracket.grid(row = 2, column = 2)
button_divide.grid(row = 2, column = 3)
window.mainloop()