2016-05-25 6 views
2

В моей программе я хотел бы обновить свой gui во время ввода пользователем. По соображениям ресурса я бы хотел только сделать это, если пользователь не набрал что-то за миллисекунды. Вот пример, который работает, но мне это не очень нравится, потому что ему нужны две дополнительные функции и немного подробный.Подождите, пока пользователь не перестанет печатать в Tkinter

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() 

Есть ли лучший способ сделать это?

+3

Возможно, вы сможете использовать необязательные функции проверки виджета 'Entry', чтобы записать время последнего нажатия клавиши, а затем проверить это значение в функции обратного вызова' after() '. Подробности о проверке виджета «Вход» [здесь] (http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/entry-validation.html). – martineau

ответ

2

Решение заключается в использовании 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() 
+0

Удивительный! Большое спасибо. Решение с функцией отмены очень элегантно, и я понятия не имел, что он существует. Очень полезно – Jannick

+0

Привет, спасибо за этот полезный код Брайан. Я пытаюсь сделать то же самое без класса. У вас есть 'after (1000, self.change_color)' bound to' .self' Когда я пытаюсь связать его с виджетами или корневыми элементами, он замораживает 1000 для каждого '' ... ... необходимо привязать это к кадру виджет, как у вас есть, или как наилучшим образом решить эту проблему? – Rhys

+0

@Rhys: Я не совсем понимаю вашу терминологию. Команде 'after' должна быть предоставлена ​​ссылка на функцию, которая должна быть вызвана. Не имеет значения, является ли эта функция частью класса или нет. Вы никогда не привязываете его к виджету ввода или любому другому виджету - вы привязываете его к функции. –

Смежные вопросы