I have a Python 3.5 app using tkinter and create/remove widgets in a canvas on the fly. I noticed that when a widget is being destroyed using w.destroy() during the callback of a window resize, the callback finished correctly, but the window is being reset to its original size.
I've tried to delay the w.destroy() using self.after(1000, self.resize) and that kind off works but when dragging/holding the cursor down while the callback is being fired, the resize jumps back anyway.
Anyone having a suggestion to remove widgets on the fly and release memory?
UPDATE: As a workaround I mark widgets to be deleted with w.delete=True and in an 'after' callback delete the widgets which are marked for deletion.
Here is a stripped down sample to illustrate the issue:
UPDATE: Simplified code to bare minimum to reproduce issue.
from tkinter import ALL, N, E, W, S, Canvas, Tk, ttk
class Resize(Tk):
def __init__(self):
super().__init__()
self.init = True
self.canvas = None
self.position_window()
self.create_canvas()
def resize(self):
if self.init:
self.init = False
return
# delete(ALL) will remove the widget from the display, but widget
# remains in memory as child of canvas. Resizing works ok.
self.canvas.delete(ALL)
# widget.destroy() will release memory of widget, but blocks/resets resizing.
# Window gets resized by 1-2 pixels and jumps back to its original size.
[child.destroy() for child in self.canvas.winfo_children()]
def create_canvas(self):
self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
self.canvas = Canvas(self)
self.canvas.grid(row=0, column=0, sticky=(N, S, W, E))
self.canvas.bind('<Configure>', lambda *args: self.resize())
entry = ttk.Label(self.canvas, text='Some dummy text')
self.canvas.create_window(20, 20, window=entry, anchor='w')
def position_window(self):
self.resizable(1, 1)
sceenwidth = self.winfo_screenwidth()
screenheight = self.winfo_screenheight()
self.update_idletasks()
width = 600
height = 300
left = sceenwidth / 2 - width / 2
top = (screenheight / 2 - height / 2) / 3
self.geometry("%dx%d%+d%+d" % (width, height, left, top))
if __name__ == '__main__':
Resize().mainloop()