Search code examples
pythonpython-2.7user-interfacetkinterpython-idle

Can't find my error in tt060.py in "Thinking in Tkinter" tutorial


The following code is the source code from the tutorial "Thinking in Tkinter".

The file is called tt060.py, a small tutorial on event binding. Below the code is the traceback that I get from IDLE (Py/IDLE ver2.7.3 - Tk ver 8.5). What is wrong with the following code that makes it not run correctly and give an error?

from Tkinter import *

class MyApp:
    def __init__(self, parent):
        self.myParent = parent
        self.myContainer1 = Frame(parent)
        self.myContainer1.pack()

        self.button1 = Button(self.myContainer1)
        self.button1.configure(text="OK", background= "green")
        self.button1.pack(side=LEFT)
        self.button1.bind("<Button-1>", self.button1Click)  #

        self.button2 = Button(self.myContainer1)
        self.button2.configure(text="Cancel", background="red")
        self.button2.pack(side=RIGHT)
        self.button2.bind("<Button-1>", self.button2Click)  #

        def button1Click(self, event):
            if self.button1["background"] == "green":
                self.button1["background"] = "yellow"
            else:
                self.button1["background"] = "green"

        def button2Click(self, event):
            self.myParent.destroy()

root = Tk()
myapp = MyApp(root)
root.mainloop()

Traceback:

Traceback (most recent call last):
  File "C:/Current/MY_PYTHON/ThinkingInTkinter/tt060.py", line 29, in <module>
    myapp = MyApp(root)
  File "C:/Current/MY_PYTHON/ThinkingInTkinter/tt060.py", line 12, in __init__
    self.button1.bind("<Button-1>", self.button1Click)  #
AttributeError: MyApp instance has no attribute 'button1Click'

The first thing I tried, as suggested in the tutorial, was to comment out the root.mainloop() line (no go - I put the line back in). I then removed self. from the event names (lines 12 & 17) to see if that had any effect (nope). I then tried putting the 2 method definitions before the .bind lines to see if that had any effect (nope). I can make it work if I just use the command options, but the tutorial is on event binding, so I'm wondering why the above code will not work?


Solution

  • You have an indentation problem. You need to start each def at the same column:

    from Tkinter import *
    
    class MyApp:
        def __init__(self, parent):
            self.myParent = parent
            self.myContainer1 = Frame(parent)
            self.myContainer1.pack()
    
            self.button1 = Button(self.myContainer1)
            self.button1.configure(text="OK", background= "green")
            self.button1.pack(side=LEFT)
            self.button1.bind("", self.button1Click)  #
    
            self.button2 = Button(self.myContainer1)
            self.button2.configure(text="Cancel", background="red")
            self.button2.pack(side=RIGHT)
            self.button2.bind("", self.button2Click)  #
    
        def button1Click(self, event):
            if self.button1["background"] == "green":
               self.button1["background"] = "yellow"
            else:
               self.button1["background"] = "green"
    
        def button2Click(self, event):
            self.myParent.destroy()
    
    root = Tk()
    myapp = MyApp(root)
    root.mainloop()