Calculator App problem in tkinter - Python

Viewed 79

In my calculator app, I want to restrict the user in performing the following operation.

Do not type an input directly in the entry box. All input should be generated through the buttons meant for numbers and mathematical operations. I do not want to enable or disable the state of entry box as it does not appear elegant. Can anybody throw some light on this. I am posting the code below:

from tkinter import *
window = Tk()
window.geometry("312x344")
window.resizable(0,0)
window.title("Calculator")

# 'btn_click' function continuously updates the input field whenever you enters a number

def btn_click(item):
   global expression
   expression = expression + str(item)
   input_text.set(expression)

# 'btn_clear' function clears the input field

def btn_clear():
   global expression
   expression = " "
   input_text.set(" ")

# 'btn_equal' calculates the expression present in input field

def btn_equal(): 
   global expression
   result = str(eval(expression))
   input_text.set(result)

expression = " "

input_text = StringVar()

input_frame = Frame(window, width = 312, height = 50, bd = 0, highlightbackground = "black", highlightcolor = "black", highlightthickness = 1)
input_frame.pack(side = TOP)

input_field = Entry(input_frame, font = ('arial', 18, 'bold'), textvariable = input_text, width = 50, bg = "#eee", bd = 0, justify = RIGHT)
input_field.grid(row = 0, column = 0)
input_field.pack(ipady = 10)

btns_frame = Frame(window, width = 312, height = 272.5, bg = "grey")
btns_frame.pack()

clear = Button(btns_frame, text = "C", fg = "black", width = 32, height = 3, bd = 0, bg = "#eee", cursor = "hand2", command = lambda: btn_clear()).grid(row = 0, column = 0, columnspan = 3,padx = 1, pady = 1)
divide = Button(btns_frame, text = "/", fg = "black", width = 10, height = 3, bd = 0, bg = "#eee", cursor = "hand2", command = lambda: btn_click("/")).grid(row = 0, column = 3,padx = 1, pady = 1)

seven = Button(btns_frame, text = "7", fg = "black", width = 10, height = 3, bd = 0, bg = "#fff", cursor = "hand2", command = lambda: btn_click(7)).grid(row = 1, column = 0, padx = 1, pady = 1)
eight = Button(btns_frame, text = "8", fg = "black", width = 10, height = 3, bd = 0, bg = "#fff", cursor = "hand2", command = lambda: btn_click(8)).grid(row = 1, column = 1, padx = 1, pady = 1)
nine = Button(btns_frame, text = "9", fg = "black", width = 10, height = 3, bd = 0, bg = "#fff", cursor = "hand2", command = lambda: btn_click(9)).grid(row = 1, column = 2, padx = 1, pady = 1)
multiply = Button(btns_frame, text = "*", fg = "black", width = 10, height = 3, bd = 0, bg = "#eee", cursor = "hand2", command = lambda: btn_click("*")).grid(row = 1, column = 3, padx = 1, pady = 1)

four = Button(btns_frame, text = "4", fg = "black", width = 10, height = 3, bd = 0, bg = "#fff", cursor = "hand2", command = lambda: btn_click(4)).grid(row = 2, column = 0, padx = 1, pady = 1)
five = Button(btns_frame, text = "5", fg = "black", width = 10, height = 3, bd = 0, bg = "#fff", cursor = "hand2", command = lambda: btn_click(5)).grid(row = 2, column = 1, padx = 1, pady = 1)
six = Button(btns_frame, text = "6", fg = "black", width = 10, height = 3, bd = 0, bg = "#fff", cursor = "hand2", command = lambda: btn_click(6)).grid(row = 2, column = 2, padx = 1, pady = 1)
minus = Button(btns_frame, text = "-", fg = "black", width = 10, height = 3, bd = 0, bg = "#eee", cursor = "hand2", command = lambda: btn_click("-")).grid(row = 2, column = 3, padx = 1, pady = 1)

one = Button(btns_frame, text = "1", fg = "black", width = 10, height = 3, bd = 0, bg = "#fff", cursor = "hand2", command = lambda: btn_click(1)).grid(row = 3, column = 0, padx = 1, pady = 1)
two = Button(btns_frame, text = "2", fg = "black", width = 10, height = 3, bd = 0, bg = "#fff", cursor = "hand2", command = lambda: btn_click(2)).grid(row = 3, column = 1, padx = 1, pady = 1)
three = Button(btns_frame, text = "3", fg = "black", width = 10, height = 3, bd = 0, bg = "#fff", cursor = "hand2", command = lambda: btn_click(3)).grid(row = 3, column = 2, padx = 1, pady = 1)
plus = Button(btns_frame, text = "+", fg = "black", width = 10, height = 3, bd = 0, bg = "#eee",    cursor = "hand2", command = lambda: btn_click("+")).grid(row = 3, column = 3, padx = 1, pady = 1)

zero = Button(btns_frame, text = "0", fg = "black", width = 21, height = 3, bd = 0, bg = "#fff", cursor = "hand2", command = lambda: btn_click(0)).grid(row = 4, column = 0, columnspan = 2, padx = 1, pady = 1)
point = Button(btns_frame, text = ".", fg = "black", width = 10, height = 3, bd = 0, bg = "#eee", cursor = "hand2", command = lambda: btn_click(".")).grid(row = 4, column = 2, padx = 1, pady = 1)
equals = Button(btns_frame, text = "=", fg = "black", width = 10, height = 3, bd = 0, bg = "#eee", cursor = "hand2", command = lambda: btn_equal()).grid(row = 4, column = 3, padx = 1, pady = 1)

window.mainloop()
2 Answers

Add the following line: 37.

input_field.config(state='disabled')

An alternative to setting state = 'disabled' is to bind the key event to a function that returns 'break'. This stops the default action of the key presses being performed for the Entry widget

import tkinter as tk 

root = tk.Tk()

entry = tk.Entry( root )

entry.grid( row = 0, column = 0, columnspan = 3 )

def inactive( event ):
    return 'break'        # Halts the default action of the event

entry.bind( '<Key>', inactive ) # The entry no longer responds to key presses
# entry.bind( '<Key>', lambda e: 'break' ) # As lambda if you prefer

def button_cmd( char ):
    entry.insert( tk.END, char )

button0 = tk.Button( root, text = '0', command = lambda: button_cmd( '0' ) )
button1 = tk.Button( root, text = '1', command = lambda: button_cmd( '1' ) )
button2 = tk.Button( root, text = '2', command = lambda: button_cmd( '2' ) )

button0.grid( row = 2, column = 0 )
button1.grid( row = 2, column = 1 )
button2.grid( row = 2, column = 2 )

root.mainloop()
Related