Python Forum

Full Version: Locking Canvas to a Window
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I've searched and experimented but am unable to solve my problem with canvas. I have been teaching myself Python. I first wrote a text program to test my knowledge of lists, dictionaries, etc. The program runs well. It's not a useful program but does provide me practice in doing various things. I then spent time converting it to a GUI. The GUI version works well (from my perspective); however, one issue, a minor one but it's bugging me, still exists.

I create my window and then I create a canvas. Inside the canvas, place an image. That all works fine. The problem comes when I call a method from a class - the method works just fine but the image disappears. I actually have two classes - the super class that performs actions relative to adding, editing, deleting records, and a method (here) displaying the dictionary records and a subclass that performs the menubar. Here's some of the code:

class People:
        # abbreviated class; only showing two methods
        def __init(self):
            self.frame = Frame(window
        
        def view_records(self):

            self.frame.destroy()     
            self.frame = Frame(window)  
            self.frame.configure(bg='light green')
            self.frame.grid(row=0, column=0)
            
            """ I tried recreating the canvas and that didn't work. """
#            canvas = Canvas(window, bg='light green', width=245, height=245)
#            image = ImageTk.PhotoImage(Image.open("picture.png"))  	# open the Army file
#            canvas.create_image(0, 0, anchor=NW, image=image)  		# draw the image

            current_row = 10  
            for key in self.people:  
                person = 'Record: ' + str(key) + str(self.people[key])
                label = Label(self.frame, text=person, bg='light green', font=('Helvetica', 8, 'bold'))
                label.grid(row=current_row, column=2, sticky=W)
                current_row += 1  
            
window = Tk()  
window.title("People System")  

window.geometry("750x300+325+200")
window.configure(bg='light green')

canvas = Canvas(window, bg='light green', width=245, height=245)
image = ImageTk.PhotoImage(Image.open("picture.png"))  	# open the Army file
canvas.create_image(0, 0, anchor=NW, image=image)  		# draw the image

""" padx and pady do put the window on the far right if I adjust 'padx'; however, if I run
    'view_records', the image disappears. """
canvas.grid(row=0, column=3, padx=500, pady=0, sticky=W)  

people = CreateMenu()  				
people.view_records()

window.mainloop()  					
Any help would be greatly appreciated.
Thanks,

Nick.
The image is being garbage collected because the only reference to image is destroyed as soon as the code returns from view_records.. Try using a global variable or an instance variable instead of the local variable "image" in method "view_records".
I don't think I was really clear about what I'm trying to achieve. I'm trying to put the image on the far right of the window and when I run any of the methods, it doesn't move and the image is always visible. If I put the image at x=0, y=0, it all works; however, as each method is called (add_record, edit_record, delete_record, or show_records), the image moves around the window.

In advance, thank you!

Nick.

Thank you, deanhystad, I'll try that. What, in my code, is destroying the image?

Nick.
All objects in python have a reference count. When the reference count goes to zero, the memory used by the object is reclaimed. This is called garbage collection. The image you create in method "view_records" is only referenced by the local variable "image". When the method is done, the local variables are deleted and nobody is referencing the image you just created.
Is this what you are referring to? No change. I'm obviously missing something; doing some research on 'garbage collection in Python'.

    def view_records(self):

        """ Display all records in the dictionary, one record per line. """

        self.frame.destroy()  # clear the window canvas
        self.frame = Frame(window)  # create a new window canvas
        self.frame.configure(bg='light green')
        self.frame.grid(row=0, column=0)

        global canvas
        canvas = Canvas(window, bg='light green', width=245, height=245)
        global image
        image = ImageTk.PhotoImage(Image.open("picture.png"))  	
        canvas.create_image(0, 0, anchor=NW, image=image)  		
        current_row = 10                                
        for key in self.people:                         
            person = 'Record: ' + str(key) + str(self.people[key])
            label = Label(self.frame, text=person, bg='light green', font=('Helvetica', 8, 'bold'))
            label.grid(row=current_row, column=2, sticky=W)
            current_row += 1                            # use the next row for the next record