0

I have a tkinter application that searches through a list of about 100000 wordlist when user types into the Entry widget (using trace with write callback to capture change in Entry variable).

I want to implement sort of a delay in order to NOT invoke the trace callback (to search the entire 100k wordlist) at EVERY keystroke (as the user might still be typing and it can become rather jerky/slow to invoke the callback function for each keystroke), rather I want to employ some sort of a min time to wait for additional input/keystroke AND/OR a max time since the first key was pressed BEFORE invoking the trace callback function.

I tried implementing a sleep but that is just a blocking call and does not achieve the desired affect. Here is some sample code where entering the string 'password' will invoke the callback (since this is literally just checking against the string 'password', it is super fast, yet in my app I loop over 100k word list for each keystroke which becomes slow). Thank You!

import tkinter as tk
from tkinter import ttk

class App(tk.Tk):
    SUCCESS = 'Success.TLabel'

    def __init__(self):
        super().__init__()
        self.title('Enter <password>')
        self.geometry("200x120")
        self.passwordVariable = tk.StringVar()
        self.passwordVariable.trace('w', self.validate)
        password_entry = ttk.Entry(
            self, textvariable=self.passwordVariable) #, show='*'
        password_entry.grid(column=0, row=1)
        password_entry.focus()
        self.message_label = ttk.Label(self)
        self.message_label.grid(column=0, row=0)

    def set_message(self, message, type=None):
        self.message_label['text'] = message
        if type:
            self.message_label['style'] = type

    def validate(self, *args):
        confirm_password = self.passwordVariable.get()
        if confirm_password == "password":
            self.set_message(
                "Success: The new password looks good!", self.SUCCESS)
            return
        if confirm_password.startswith("pas"):
            self.set_message('Warning: Keep entering the password')

if __name__ == "__main__":
    app = App()
    app.mainloop()
8
  • The way you implement delays in a Tkinter application is the .after() method. In your particular case, save the return value from the method - if the trace is invoked again, you can use .after_cancel() to end the current delay, and then start a new one. Commented Mar 23, 2022 at 1:19
  • Could you please elaborate? I am not sure exactly what you mean/how to implement your suggestion. Commented Mar 23, 2022 at 2:02
  • Where exactly do you run this 100K word scanning? Commented Mar 25, 2022 at 12:44
  • @DelriusEuphoria, Its a list in my app that I loop thru for every trace callback. For the purposes of this question I simply need help with adding some sort of a delay before the trace callback gets invoked. Commented Mar 26, 2022 at 4:15
  • Yes but I need to know "when" you need the delay Commented Mar 26, 2022 at 14:40

1 Answer 1

1

I tried to understand what your current code does so I can implement the function here, but I've had no luck. Hopefully you being the author can implement this example onto your code.

The idea here is to schedule a callback to run after x seconds and if it is already scheduled, then cancel it. Sort of like a timer, if you think about it.

from tkinter import *

root = Tk()
SECONDS_TO_WAIT = 1
rep = None

def typing(*args):
    global rep
    if rep is None:
        writing.config(text='Typing...')
    else:
        root.after_cancel(rep) # if already scheduled, then cancel it
    
    rep = root.after(SECONDS_TO_WAIT*1000, caller) 

def caller(*args):
    global rep
    writing.config(text='Not typing')
    rep = None # Set it to None if `caller` GETS executed

var = StringVar()
entry = Entry(root,textvariable=var)
entry.pack(padx=10,pady=10)
entry.focus_force()

writing = Label(root,text='Not typing')
writing.pack()
var.trace('w',typing)

root.mainloop()

This will execute typing each time the entry widget is edited/written to. And according to the conditions inside the function, caller gets executed.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.