Python Forum
[Tkinter] Locking Canvas to a Window - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: GUI (https://python-forum.io/forum-10.html)
+--- Thread: [Tkinter] Locking Canvas to a Window (/thread-27390.html)



Locking Canvas to a Window - drnshaw - Jun-05-2020

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.


RE: Locking Canvas to a Window - deanhystad - Jun-05-2020

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".


RE: Locking Canvas to a Window - drnshaw - Jun-05-2020

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.


RE: Locking Canvas to a Window - deanhystad - Jun-05-2020

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.


RE: Locking Canvas to a Window - drnshaw - Jun-06-2020

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