manty
manty

Reputation: 297

What's wrong with this following Tkinter program?

I'm trying to execute my first tkinter app, but it's giving me error as shown below. Any idea why 'frame' is not visible to a function of the same class ?

Traceback (most recent call last):
File "C:\Data\Personal\Python\Tkinter\GUI_ver1.py", line 25, in <module>
myapp = App(root)
File "C:\Data\Personal\Python\Tkinter\GUI_ver1.py", line 7, in __init__
self.createWidgets()
File "C:\Data\Personal\Python\Tkinter\GUI_ver1.py", line 10, in createWidgets
self.button = Button(frame, text="QUIT", fg="red", command=frame.quit)
NameError: global name 'frame' is not defined

My program below:

from Tkinter import *

class App(Frame):
    def __init__(self, master=None):
        frame = Frame(master)
        frame.pack()
        self.createWidgets()

    def createWidgets(self):
        self.button = Button(frame, text="QUIT", fg="red", command=frame.quit)
        self.button.pack(side=LEFT)

        self.hi_there = Button(frame, text="Hello", command=self.say_hi)
        self.hi_there.pack(side=LEFT)

        self.hi_there.pack({"side": "right"})

    def say_hi(self):
        print "hi there, everyone!"

root = Tk()
# create the application
myapp = App(root)

myapp.master.title("My First App")
myapp.master.geometry('450x130')
myapp.master.resizable(0,0)

# start the program
root.mainloop()

Upvotes: 0

Views: 755

Answers (1)

Kevin
Kevin

Reputation: 76194

def __init__(self, master=None):
    frame = Frame(master)
    frame.pack()
    self.createWidgets()

The frame you defined in __init__ is not visible in any other methods. If you want to be able to access it, you need to make it an attribute of self.

def __init__(self, master=None):
    self.frame = Frame(master)
    self.frame.pack()
    self.createWidgets()

Don't forget to include the self. whenever you use the variable.

def createWidgets(self):
    self.button = Button(self.frame, text="QUIT", fg="red", command=self.frame.quit)
    self.button.pack(side=LEFT)

    self.hi_there = Button(self.frame, text="Hello", command=self.say_hi)
    self.hi_there.pack(side=LEFT)

That's the easiest way to resolve the NameError, but your code will still crash with an AttributeError: App instance has no attribute 'master' error. This is happening because, although you made App a subclass of Frame, you never call the Frame initializer for it, so it gets confused when you try to invoke Frame methods. Remember to call __init__.

def __init__(self, master=None):
    Frame.__init__(self, master)
    frame = Frame(master)
    frame.pack()
    self.createWidgets()

With that last addition, your code should work properly, but it's a little more complicated than it needs to be. Your App instance is a frame, but it also contains a frame within itself, self.frame. You could simplify this by removing the second frame and just adding widgets directly to self.

class App(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.pack()
        self.createWidgets()

    def createWidgets(self):
        self.button = Button(self, text="QUIT", fg="red", command=self.quit)
        self.button.pack(side=LEFT)

        self.hi_there = Button(self, text="Hello", command=self.say_hi)
        self.hi_there.pack(side=LEFT)

        self.hi_there.pack({"side": "right"})

Upvotes: 3

Related Questions