Reputation: 23154
Here is the code:
#!/usr/bin/env python3
################################################################
### Solve the unknown
################################################################
class App:
def __init__(self, root):
self.fields = ["A", "B", "AB"]
self.root = root
self.entries = []
self.numerics = []
self.makeRows()
Button(self.root, text="Run", command=self.run).grid(row=3, column=0)
Button(self.root, text="Reset", command=self.reset).grid(row=3, column=1)
root.bind("<Return>", self.run)
root.bind("<space>", self.reset)
def makeRows(self):
for i in range(len(self.fields)):
label = Label(self.root, text=self.fields[i], justify=LEFT)
entry = Entry(self.root)
label.grid(row=i, sticky=W)
entry.grid(row=i, column=1)
self.entries.append(entry)
def getValues(self):
try:
values = [e.get() for e in self.entries]
self.numerics = [float(v) if v!="" else v for v in values]
print(self.numerics)
except ValueError:
messagebox.showerror(title="Error", message="Input only numerical values!")
self.numerics = []
def checkEmpty(self, elem):
if elem == "":
return 1
else:
return 0
def checkEmptyInEntries(self):
if len(self.numerics) != 0:
entry_emptiness = [self.checkEmpty(v) for v in self.numerics]
if sum(entry_emptiness) != 1:
messagebox.showerror(title="Error", message="Leave one and only one entry empty!")
return None
return entry_emptiness
else:
return None
def run(self):
self.getValues()
emptiness = self.checkEmptyInEntries()
if emptiness == None:
return None
empty_index = emptiness.index(1)
if empty_index == 0:
self.entries[0].delete(0, END)
self.entries[0].insert(0, str(self.numerics[2] / self.numerics[1]))
elif empty_index == 1:
self.entries[1].delete(0, END)
self.entries[1].insert(0, str(self.numerics[2] / self.numerics[0]))
else:
self.entries[2].delete(0, END)
self.entries[2].insert(0, str(self.numerics[0] * self.numerics[1]))
def reset(self):
for entry in self.entries:
entry.delete(0, END)
from tkinter import *
root = Tk()
app = App(root)
root.mainloop()
The buttons work fine, but whenever I press enter, Python complains:
TypeError: run() takes 1 positional argument but 2 were given
Upvotes: 0
Views: 114
Reputation:
Using bind
to bind events to callbacks causes an event object to be sent to the callback every time the binding is invoked. You need to handle this extra argument. The easiest way to do this is to use a lambda
function:
root.bind("<Return>", lambda _: self.run())
In the above code, the _
will be the event object.
Note that you could also change the definition of run
to accept this object:
def run(self, event):
But I personally prefer the lambda
because it makes it clearer that run
does not use the event object.
Upvotes: 3