Kube Kubow
Kube Kubow

Reputation: 428

Trace Tkinter variable with a delay

I would like to filter dataset with a delay.

I have this basic layout:

import tkinter as tk
    
def filter(*args):
   print('entry callback', 'changed %s' % str(args))
   print('limit result set with', filter_input.get())

if __name__ == "__main__":
    master = tk.Tk()
    filter_input = tk.StringVar(value='')  # filter mode
    # filter_input.trace('w', filter)  # simple trace triggers immediately
    # filter_input.trace_variable('w', filter)  # trace_variable as well
    filter_input.trace_add('write', filter)  # trace_add should replace previous (deprecated)
    entry_field = tk.Entry(master, textvariable=filter_input)
    entry_field.pack()
    tk.mainloop()

I started with main Tkinter python page

I went through the main widget documentation

There are a bunch of more documentation around the globe, but I can't find anywhere any mention about a delay implemented. Can anyone help me to find out, if there is possible to call the filter function after some defined amount of time? Maybe another wrapper function could help?

EDIT:

It looks like I need to clear out the desired functionality. This is somehow what I am after but I need a delay instead of "user-stops-typing" activity.

Upvotes: 1

Views: 491

Answers (1)

Delrius Euphoria
Delrius Euphoria

Reputation: 15098

If you just want to call the function with a delay then use after(ms,func) to call the function after ms milliseconds. So your function could be like:

def filter(*args):
    # print(f'entry callback changed {str(args)}')
    print(f'limit result set with {filter_input.get()}')
    master.after(1000,filter) # Call this function every 1000 millisecond or 1 second

if __name__ == "__main__":
    master = tk.Tk()
    ....
    
    filter() # Call the function initially
    tk.mainloop()

So you can also get rid of StringVar here as you are using after() and nothing else. If you want to end this after() loop, then use after_cancel(id).

EDIT:

If you want to see the input with just a delay once each time the window is open, then try this:

first = True
def show():
    global first
    if first and entry_field.get():
        first = False
        master.after(3000,lambda: print(entry_field.get()))

if __name__ == "__main__":
    master = tk.Tk()

    ......
    entry_field.bind('<Key>',lambda e: show())    

EDIT 2: This will call the function also when the box is cleared and typed again:

first = True
def show():
    global first
    if entry_field.get():
        if first:
            first = False
            master.after(3000,lambda: print(entry_field.get()))
    else:
        first = True

Upvotes: 2

Related Questions