开发者

I want to limit how often a Tkinter callback is run

开发者 https://www.devze.com 2023-01-07 13:16 出处:网络
I\'m writing my first GUI program with Tkinter (first program in Python too, actually). I have an Entry widget for searching, and the results go to a Listbox. I want the results to update as the user

I'm writing my first GUI program with Tkinter (first program in Python too, actually).

I have an Entry widget for searching, and the results go to a Listbox. I want the results to update as the user types, so I made a callback like this:

search_field.bind("<KeyRelease>", update_results)

The problem is that updates the search many times in a row. Since the results will be coming from a database query, that generates a lot of unnecessary traffic. What I really want is for it to update every second or so, or to wait a second after the user stops typing and then search. What's the easiest way to do that? Thanks

UPDATE: That works great for what I described, but now I've realized that I also need to trigger an update aft开发者_运维百科er the user stops typing. Otherwise, the last few characters are never included in the search. I think I have to un-accept the answer in order for this to go back into the list of questions...


A nice way to do this is a simple caching decorator:

import time
def limit_rate( delay=1.0 ):
    """ produces a decorator that will call a function only once per `delay` """
    def wrapper( func ): # the actual decorator
        cache = dict( next = 0 ) # cache the result and time
        def limited( *args, **kwargs):
            if time.time() > cache['next']: # is it time to call again
                cache['result'] = func( *args, **kwargs) # do the function
                cache['next'] = time.time() + delay # dont call before this time
            return cache['result']
        return limited
    return wrapper

It works like this:

@limit_rate(1.5)
def test():
    print "Called test()"
    time.sleep( 1 )
    return int(time.time())

print [test() for _ in range(5)] # test is called just once

You would simply add this decorator somewhere and decorate your update_results function with it.


Figured it out. I call the decorated function with a delay using any_widget.after(delay_in_ms, function).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号