Подождите, пока пользователь не перестанет печатать в Tkinter
В моей программе я хотел бы обновить свой графический интерфейс, пока пользователь набирает текст. По соображениям ресурса я бы, однако, хотел сделать это только в том случае, если пользователь не набрал что-то за x миллисекунд. Вот пример, который работает, но мне он не очень нравится, потому что он требует двух дополнительных функций и немного многословен.
import tkinter as tk
import random
COLORS =["red", "orange", "yellow", "green", "blue", "violet"]
class Application(tk.Frame):
def __init__(self,master):
self.counter = 0
self.master = master
tk.Frame.__init__(self)
self.pack()
self.entry = tk.Entry(self)
self.entry.pack()
self.entry.bind('<Key>',lambda event: self.handle_wait(event))
def handle_wait(self,event):
self.counter += 1
counter = self.counter
self.after(1000,lambda: self.handle_wait2(counter) )
def handle_wait2(self,counter):
if self.counter == counter:
self.change_color()
def change_color(self):
random_color = random.choice(COLORS)
self.entry.config(background=random_color)
root = tk.Tk()
app = Application(root)
app.mainloop()
Есть ли лучший способ сделать это?1 ответ:
Решение состоит в том, чтобы использовать
after
для планирования запуска функции после того, как пользователь перестанет печатать. Затем все, что вам нужно сделать, это перезапустить работу каждый раз, когда вы получаете щелчок кнопки.Сначала создайте переменную для хранения идентификатора, представляющего будущий вызов функции. Вы также можете выбросить
self.counter
, поскольку это не нужно.def __init__(...): ... self._after_id = None ...
Затем удалите лямбду из привязки. Это бессмысленно и делает код более сложным, чем он должен быть:
self.entry.bind('<Key>',self.handle_wait)
Наконец, измените свою функцию
handle_wait
на выглядит так:def handle_wait(self, event): # cancel the old job if self._after_id is not None: self.after_cancel(self._after_id) # create a new job self.after(1000, self.change_color)
Вот полный пример, основанный на вашем коде:
import tkinter as tk import random COLORS =["red", "orange", "yellow", "green", "blue", "violet"] class Application(tk.Frame): def __init__(self,master): self.master = master tk.Frame.__init__(self) self.pack() self._after_id = None self.entry = tk.Entry(self) self.entry.pack() self.entry.bind('<Key>',self.handle_wait) def handle_wait(self,event): # cancel the old job if self._after_id is not None: self.after_cancel(self._after_id) # create a new job self._after_id = self.after(1000, self.change_color) def change_color(self): random_color = random.choice(COLORS) self.entry.config(background=random_color) root = tk.Tk() app = Application(root) app.mainloop()