Campop
Campop

Reputation: 3

Canvas objects won't recreate for Tkinter

I'm having a problem where I'm trying to make a simple mathematics game and I have buttons that will take a user back to the main menu from an 'Instructions' frame. The problem is that when I click on the button to go back into the 'Instructions' frame, none of the canvas objects will display the second time it creates them. Here is my code:

from tkinter import *

class GUI:
    def __init__(self, parent):

        self.parent = parent

#==============================================================================
#CREATE MENU FRAMES
#==============================================================================
        self.menu_frame = Frame(parent, width = 800, height = 600)
        self.menu_frame.pack_propagate(0)

        self.create_menu()

#==============================================================================
#CREATE HTP AND SETTINGS FRAME
#==============================================================================
        self.initial_frame = Frame(parent, width = 800, height = 600)
        self.initial_frame.pack_propagate(0)
#==============================================================================
#CREATE HOW TO PLAY FRAME
#==============================================================================
        self.htp_frame = Frame(parent, width = 800, height = 600)
        self.htp_frame.pack_propagate(0)

#==============================================================================
#CREATE SETTINGS FRAME
#==============================================================================
        self.settings_frame = Frame(parent, width = 800, height = 600)
        self.settings_frame.pack_propagate(0)


    def create_menu(self):

        self.menu_frame.pack()

        self.canvas = Canvas(self.menu_frame, width=800, height=600)
        self.canvas.background = PhotoImage(file = "images/math_background.gif")
        self.canvas.pack(expand = YES, fill = BOTH)
        self.canvas.create_image(400, 300, image=self.canvas.background)

        self.menu_text = Label(self.menu_frame, text = "Mathematics Program", font = ("Rockwell", "36", "bold"), fg = "black", pady = 30)
        self.menu_text.pack()

        self.start_button = Button(self.menu_frame, text = "Start", font = ("Arial", "18", "bold"), width = 30, bg = "Light Goldenrod Yellow")
        self.start_button.pack()
        self.canvas.create_window(400, 200, window=self.start_button)
        self.instructions_button = Button(self.menu_frame, text = "How to Play", font = ("Arial", "18", "bold"), width = 30, bg = "Light Goldenrod Yellow", command = self.create_htp)
        self.instructions_button.pack()
        self.canvas.create_window(400, 300, window=self.instructions_button)
        self.settings_button = Button(self.menu_frame, text = "Settings", font = ("Arial", "18", "bold"), width = 30, bg = "Light Goldenrod Yellow", command = self.create_settings)
        self.settings_button.pack()
        self.canvas.create_window(400, 400, window=self.settings_button)
        self.quit_button = Button(self.menu_frame, text = "Quit", font = ("Arial", "18", "bold"), width = 30,bg = "Light Goldenrod Yellow", command = self.quit_program)
        self.quit_button.pack()
        self.canvas.create_window(400, 500, window=self.quit_button)
        self.canvas.create_text(400, 100, text = "Mathematics Program", font = ("Rockwell", "36", "bold"), fill = "Light Goldenrod Yellow")



    def create_bg(self):
        self.menu_frame.pack_forget()
        self.initial_frame.pack()
        self.canvas2 = Canvas(self.initial_frame, width=800, height = 600)
        self.canvas2.pack(expand = YES, fill = BOTH)
        self.canvas2.initial_background = PhotoImage(file = "images/orange_bg.gif")
        self.canvas2.create_image(400, 300, image=self.canvas2.initial_background)

    def create_htp(self):
        self.create_bg()
        self.canvas2.create_text(400, 100, font = ("Arial", "28", "bold"), fill = "Light Goldenrod Yellow", justify = CENTER, text = "Instructions", tag = "htp")
        self.canvas2.create_text(400, 300, font = ("Arial", "14", "bold"), fill = "Light Goldenrod Yellow", width = 600, justify = CENTER, tag = "htp", text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque dictum, erat ut dignissim sollicitudin, lorem neque molestie erat, a interdum justo nulla sed erat. Aliquam eu adipiscing nibh, in viverra diam. Cras dapibus lectus sed nibh lacinia eleifend. Duis a massa purus. Mauris vel turpis eu diam pharetra auctor ut ut tellus. Curabitur eget justo id sapien molestie egestas. Ut at nibh magna. Quisque id augue vitae nisl viverra tristique vel at eros. Pellentesque id risus lorem. Nullam aliquet eros tellus, a eleifend magna vehicula sit amet. Phasellus dapibus vulputate turpis, quis mattis justo consectetur sed. Curabitur porttitor vulputate eros.")
        self.menu_button1 = Button(self.initial_frame, text = "Back to Menu", font = ("Arial", "18", "bold"), width = 25,bg = "Light Goldenrod Yellow", command = self.go_to_menu)
        self.menu_button1.pack()
        self.canvas2.create_window(400, 550, window=self.menu_button1, tag = "htp")



    def create_settings(self):
        self.create_bg()


    def go_to_menu(self):
        self.initial_frame.pack_forget()
        self.canvas2.delete("all")
        self.create_menu()


    def quit_program(self):
        self.parent.destroy()


if __name__ == '__main__':
    root = Tk()
    math_program = GUI(root)
    root.title("Mathematics Program")
    root.mainloop()

Upvotes: 0

Views: 220

Answers (1)

Brionius
Brionius

Reputation: 14098

The problem lies with self.canvas2.

When you click on (1) "How to Play", then (2) "Back to Menu", then (3) "How to Play", here's what happens to self.canvas2:

  1. You create a new Canvas object, assign it to the reference self.canvas2, and pack it.
  2. You clear all the items from the Canvas referenced by self.canvas2
  3. You create a new Canvas object, assign it to the reference self.canvas2, and pack it.

Note that the original canvas object from step (1), which is now blank since you have cleared of all items, still exists as a child of self.initial_frame, even though you no longer have a local reference to it, and is in fact on top of and blocking view of your new Canvas object which you expect to see.

The quick solution is to add a destroy call to get rid of that unused Canvas object when you switch away from the How to Play frame:

def go_to_menu(self):
    self.initial_frame.pack_forget()
    self.canvas2.destroy()   #### Get rid of the old unneeded canvas
    self.create_menu()

Personally, I think it's more natural to reuse the old Canvas object, rather than delete and recreate it every time you switch back to the How to Play frame, but as it works either way, I guess it's a matter of taste.

Upvotes: 2

Related Questions