I am working on a calculator and I have encountered a problem regarding my key-binds. At the end of the initiation of my GUI class, a message box is created that explains the binds to the user.
messagebox.showinfo("Guide", "Key bindings include: 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, ., +, -, *, /, (, ), Enter, Backspace, Insert and Delete.")
Ironically, this causes all of the binds to not respond until the message box is closed and the tkinter window is deselected then reselected. The binds are coded like this:
master.bind('<Delete>', self.delete)
master.bind('<BackSpace>', self.back)
master.bind('<Return>', self.equals)
master.bind('<Insert>', self.add_answer)
I have attempted to use focus_set() but it does not help. What can I do to make my keyboard binds respond immediately after the message box is closed?
Here is the entirety of my code for context.
from tkinter import *
from tkinter.ttk import *
from tkinter import messagebox # added by @martineau
class Logic:
def add_digit(self, *args):
if type(args[0]) == str:
self.expression.append(args[0])
else:
self.expression.append(args[0].char)
self.labels[1].config(text="".join(self.expression))
def add_operation(self, *args):
if type(args[0]) == str:
self.expression.append(args[0])
else:
self.expression.append(args[0].char)
self.labels[1].config(text="".join(self.expression))
def add_answer(self, *args):
self.expression.extend(list(self.labels[0]['text']))
self.labels[1].config(text="".join(self.expression))
def delete(self, *args):
if self.expression:
self.expression = list()
self.labels[1].config(text="".join(self.expression))
else:
self.labels[0].config(text="")
def back(self, *args):
self.expression = self.expression[:-1]
self.labels[1].config(text="".join(self.expression))
def equals(self, *args):
equation = list()
number = list()
if not self.expression:
self.labels[0].config(text='')
for value in self.expression:
if value in self.numpad_texts:
number.append(value)
else:
if number:
equation.append(str(float("".join(number))))
number = list()
equation.append(value)
if number:
try:
equation.append(str(float("".join(number))))
except ValueError:
messagebox.showerror("Error", "Syntax error: Your expression has incorrect syntax")
for i in range(len(equation)):
if equation[i] == '(' and i != 0:
if equation[i-1] not in self.operation_texts:
equation.insert(i, '*')
elif equation[i] == ')' and i != len(equation)-1:
if equation[i+1] not in self.operation_texts:
equation.insert(i+1, '*')
if equation:
try:
self.labels[0].config(text=str(eval(''.join(equation))))
except ZeroDivisionError:
messagebox.showerror("Error", "Zero division error: Your expression has a division by zero")
except SyntaxError:
messagebox.showerror("Error", "Syntax error: Your expression has incorrect syntax")
class GUI(Logic):
numpad_texts = ('7', '8', '9', '4', '5', '6', '1', '2', '3', '0', '.', 'Equals')
operation_texts = ('/', '*', '-', '+', '(', ')')
function_texts = ('Delete', 'Back')
def __init__(self, master):
master.title('Calculator')
self.expression = list()
self.label_frame = Frame(master)
self.label_frame.grid(columnspan=2)
self.labels = list()
for i in range(2):
self.labels.append(Label(self.label_frame))
self.labels[i].grid(row=i, column=0, columnspan=4)
self.labels[0].bind("<Button-1>", self.add_answer)
self.numpad_frame = Frame(master)
self.numpad_frame.grid(row=1, rowspan=2)
self.numpad_buttons = list()
for i in range(len(self.numpad_texts)):
self.numpad_buttons.append(Button(self.numpad_frame, text=self.numpad_texts[i], command=lambda i=i: self.add_digit(self.numpad_texts[i])))
self.numpad_buttons[i].grid(row=i//3, column=i%3)
if self.numpad_texts != 11:
master.bind(self.numpad_texts[i], self.add_digit)
self.numpad_buttons[-1].config(command=self.equals)
self.operations_frame = Frame(master)
self.operations_frame.grid(row=1, column=1)
self.operation_buttons = list()
for i in range(len(self.operation_texts)):
self.operation_buttons.append(Button(self.operations_frame, text=self.operation_texts[i], command=lambda i=i: self.add_operation(self.operation_texts[i])))
self.operation_buttons[i].grid(row=i//2, column=i%2)
master.bind(self.operation_texts[i], self.add_operation)
self.functions_frame = Frame(master)
self.functions_frame.grid(row=2, column=1)
self.function_buttons = list()
for i in range(len(self.function_texts)):
self.function_buttons.append(Button(self.functions_frame, text=self.function_texts[i]))
self.function_buttons[i].grid(row = 0, column=i%2)
self.function_buttons[0].config(command=self.delete)
self.function_buttons[1].config(command=self.back)
master.bind('<Delete>', self.delete)
master.bind('<BackSpace>', self.back)
master.bind('<Return>', self.equals)
master.bind('<Insert>', self.add_answer)
messagebox.showinfo("Guide", "Key bindings include: 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, ., +, -, *, /, (, ), Enter, Backspace, Insert and Delete.")
if __name__ == '__main__':
root = Tk()
calculator = GUI(root)
root.mainloop()