Re: Tkinter: repeated calls to Text.window_create() gradually slow down

MRAB <[email protected]>
Newsgroups gmane.comp.python.general
Message-ID <[email protected]>
On 2025-06-10 09:39, John O'Hagan wrote:
> Hi list
> 
> I noticed this issue with a long-running application that displays
> information from a variable number of sources by opening an embedded
> window on a Text widget for each new source, and closing it when the
> source is completed. To prevent increasing memory use, the widgets
> inside the windows are "recycled", i.e. hidden using a tag and cached
> when the window is closed, to be re-used when needed. New widgets are
> only created when the cache is empty.
> 
> The code below demonstrates the issue by rapidly creating and hiding a
> window containing the same Label widget. On my machine, each
> create_window call initially takes < 1 ms, but a few minutes later
> increases to several ms. After several hours, it takes a few seconds
> for each operation.
> 
> If the commented line removing the tag is used instead of the
> window_create call, there is no slowdown. Unfortunately this is not
> useful in the real program, which requires that new windows open in a
> specified position. AFAIK there is no way to move an embedded window on
> a Text widget other than by re-calling window_create (but I'd be glad
> to be wrong about that).
> 
> Any insights or suggestions?
> 
> -------------------------------
> 
> from time import time
> from tkinter import *
> 
> root = Tk()
> button = Button(root, text='Run')
> text = Text(root)
> text.tag_config('hide', elide=True)
> label=Label(text, text='running')
> 
> def show_and_hide():
>      if button['text']=='Stop':
>          if text.tag_names(label):
>              t = time()
>              #this line gradually gets slower:
>              text.window_create(END, window=label)
>              #this line doesn't:
>              #text.tag_remove('hide', label)
>              print(round((time() - t) * 1000))
>          else:
>              text.tag_add('hide', label)
>          button.after(10, show_and_hide)
> 
> def run():
>      if button['text']=='Run':
>          button['text'] = 'Stop'
>          text.window_create(END, window=label)
>          show_and_hide()
>      else:
>          button['text'] = 'Run'
>          text.tag_add('hide', label)
> 
> button['command'] = run
> button.pack()
> text.pack()
> mainloop()

If you look at the memory usage, you'll see that it rises.

I think that's because 'window_create' adds the label each time, so the 
number of them (well, references to the single label, to be exact) in 
the text widget increases.

It's interesting that listing them with 'window_names' shows only 1, 
perhaps because they are all the same label and therefore have the same 
name. Strange though.
-- 
https://mail.python.org/mailman3//lists/python-list.python.org
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.