0

For my computer science class we have been assigned the task of making a movie kiosk. Users add items to there cart which I store in the form of lists. When the check out screen is loaded I want to added labels displaying which items the user has in their cart. I have the following code:

class CheckOut(tk.Frame): #check out page

def __init__(self, parent, controller):
    tk.Frame.__init__(self, parent)
    #create and place base widgets
    backGroundPicture = ImageTk.PhotoImage(Image.open("Background.jpg"))
    backGroundLabel = tk.Label(self, image=backGroundPicture, borderwidth=0)
    backGroundLabel.image = backGroundPicture
    backGroundLabel.place(x=0, y=0, anchor=tk.NW)

    checkOutLabel = tk.Label(self, text="Check Out", font=("Verdana", 48), bg="#001f33", fg="red")
    checkOutLabel.place(relx=0.5, rely=0, anchor=tk.N)

    returnButton = tk.Button(self, text="Return to Main Menu", bg="#4db8ff", fg="black",
                       command=lambda: controller.show_frame(StartPage))
    returnButton.place(relx=1, rely=1, anchor=tk.SE)

def update(): #add new widgets displaying items purchase
    print("debug")
    itemLists = []
    for each in movieTitles:
        i = movieTitles.index(each)
        if(adultTickets[i] != 0):
            tempLabel = tk.Label(self, text="Adult Ticket: " + str(adultTickets[i]) + " " + each)
            itemLists.append(tempLabel)
        if(childTickets[i] != 0):
            tempLabel = tk.Label(self, text="Child Ticket: " + str(childTickets[i]) + " " + each)
            itemLists.append(tempLabel)
    for i in itemLists:
        i.place(x=100, y=200, anchor=tk.CENTER)
    print(itemLists)

Everything is working except when I try to create the labels with the parent of self, It is undefined. I would like to place them in the same frame that the init method is using. How would I go about getting access to self? Is there some sort of work around I could use?

3
  • Define update() with a self argument, and call it as an instance method, not a class method. Commented Feb 23, 2016 at 17:01
  • you need to fix the indentation of your code. It's not clear if your update function is part of the class or not. Commented Feb 23, 2016 at 17:03
  • How would I call it as an instance method instead of a class method? I am calling update() from a different class if that affects anything. Indention is correct in my personal code, didn't copy and paste as I expected, sorry for the confusion. Commented Feb 24, 2016 at 2:25

1 Answer 1

1

Side note: StackOverflow expects code samples to have an additional 4-space indent. If you simply paste your code, select it in the text box and click the "Code Sample" button in the editor (labelled {}), it will add the indent.

class CheckOut(tk.Frame): #check out page
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        #create and place base widgets
        backGroundPicture = ImageTk.PhotoImage(Image.open("Background.jpg"))
        backGroundLabel = tk.Label(self, image=backGroundPicture, borderwidth=0)
        backGroundLabel.image = backGroundPicture
        backGroundLabel.place(x=0, y=0, anchor=tk.NW)

        checkOutLabel = tk.Label(self, text="Check Out", font=("Verdana", 48), bg="#001f33", fg="red")
        checkOutLabel.place(relx=0.5, rely=0, anchor=tk.N)

        returnButton = tk.Button(self, text="Return to Main Menu", bg="#4db8ff", fg="black",
                           command=lambda: controller.show_frame(StartPage))
        returnButton.place(relx=1, rely=1, anchor=tk.SE)

    ...

Methods of a class in Python pass the object as the first parameter to the method. As a convention, this parameter is named self, but really, you can give it any name.* So add self as a parameter to your update method. I suppose you also wanted to pass a the movie titles as a parameter to the update method.

    ...

    def update(self, movieTitles): #add new widgets displaying items purchase
        print("debug")
        itemLists = []
        for each in movieTitles:
            i = movieTitles.index(each)
            if(adultTickets[i] != 0):
                tempLabel = tk.Label(self, text="Adult Ticket: " + str(adultTickets[i]) + " " + each)
                itemLists.append(tempLabel)
            if(childTickets[i] != 0):
                tempLabel = tk.Label(self, text="Child Ticket: " + str(childTickets[i]) + " " + each)
                itemLists.append(tempLabel)
        for i in itemLists:
            i.place(x=100, y=200, anchor=tk.CENTER)
        print(itemLists)

This way, after having instantiated your object, you can apply its methods like this:

# instantiate object
my_frame = CheckOut(parent, controller)

# apply "update"
my_frame.update(my_movie_titles)

# The previous line has the same effect as this:
CheckOut.update(my_frame, my_movie_titles)

Note: I did not test the code, I just fixed the little syntax mistakes you had in there. At a glance, it seems like the labels for the movies will all have the same position.

Also, as user "zondo" suggests, lambdas here and there clutter the code; getting rid of them can make the code easier to read. A simple occurrence like this can be replaced with the function partial from the functools module:

from functools import partial

returnButton = tk.Button(self, ..., 
    command=partial(controller.show_frame, StartPage))
  • Other languages such as C++/Java and family will reserve a keyword instead. (this)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.