简体   繁体   中英

Why is the tk key binding not working here?

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM