自上次在 tkinter 中按下按键后经过一段时间后调用函数
Calling a function after time period has elapsed since last key press in tkinter
我在 Python 的 tkinter 应用程序中有一个条目。如果用户更改条目内容,程序将通过 onValidate
函数做出反应。
现在,如果用户有一段时间没有按下任何键,我想 select 输入字段中的所有文本。
下面我尝试使用 after
函数在 1000
毫秒后 select_all_text
,但它似乎不起作用。
import tkinter as tk
class MyEntry(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.vcmd = (self.register(self.onValidate),
'%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
self.entry = tk.Entry(self, validate="key", validatecommand=self.vcmd)
self.entry.pack(side="top", fill="x")
self.select_all_text()
def select_all_text(self):
self.entry.focus()
self.entry.select_range(0,'end')
def onValidate(self, d, i, P, s, S, v, V, W):
self.root.after(1000, self.select_all_text)
return True
if __name__ == "__main__":
root = tk.Tk()
MyEntry(root).pack(fill="both", expand=True)
root.mainloop()
此外,每次按下新键时计时器都应重置,这样 select_all_text
仅在自上次按键后经过足够长的时间后才会被调用。在下面的示例中,每次按键后都会调用 select_all_text
,这不是我们想要的行为。
我在想是否可以跟踪自上次按键以来的时间,如果超过某个阈值,则会调用函数。这样的方法也能解决问题
如果自上次在 tkinter 中按下按键以来已经过去了足够长的时间,如何调用函数?
当您保留对 after
returns 的 id 的引用时,您可以使用 after_cancel
取消它。有了这个,你可以取消预定的功能并在每次按键时重新安排它:
class MyEntry(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.parent = parent
self.after_id = None
...
def onValidate(self, d, i, P, s, S, v, V, W):
if self.after_id:
self.parent.after_cancel(self.after_id)
self.after_id = self.parent.after(1000, self.select_all_text)
return True
请注意,我还在 self.parent
中保存了您作为参数传递给 MyEntry
的根 window,并使用它来调用 after
。
P.S。您实际上并不需要 Entry 的 validatecommand
命令来执行此操作(当然,如果您已经使用了 validatecommand
,则可以)。您可以将函数绑定到每个按键:
class MyEntry(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.parent = parent
self.after_id = None
self.entry = tk.Entry(self)
self.entry.bind('<Key>', self.entry_keypress)
...
def entry_keypress(self, e):
print(self.after_id)
if self.after_id:
self.parent.after_cancel(self.after_id)
self.after_id = self.parent.after(1000, self.select_all_text)
我在 Python 的 tkinter 应用程序中有一个条目。如果用户更改条目内容,程序将通过 onValidate
函数做出反应。
现在,如果用户有一段时间没有按下任何键,我想 select 输入字段中的所有文本。
下面我尝试使用 after
函数在 1000
毫秒后 select_all_text
,但它似乎不起作用。
import tkinter as tk
class MyEntry(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.vcmd = (self.register(self.onValidate),
'%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
self.entry = tk.Entry(self, validate="key", validatecommand=self.vcmd)
self.entry.pack(side="top", fill="x")
self.select_all_text()
def select_all_text(self):
self.entry.focus()
self.entry.select_range(0,'end')
def onValidate(self, d, i, P, s, S, v, V, W):
self.root.after(1000, self.select_all_text)
return True
if __name__ == "__main__":
root = tk.Tk()
MyEntry(root).pack(fill="both", expand=True)
root.mainloop()
此外,每次按下新键时计时器都应重置,这样 select_all_text
仅在自上次按键后经过足够长的时间后才会被调用。在下面的示例中,每次按键后都会调用 select_all_text
,这不是我们想要的行为。
我在想是否可以跟踪自上次按键以来的时间,如果超过某个阈值,则会调用函数。这样的方法也能解决问题
如果自上次在 tkinter 中按下按键以来已经过去了足够长的时间,如何调用函数?
当您保留对 after
returns 的 id 的引用时,您可以使用 after_cancel
取消它。有了这个,你可以取消预定的功能并在每次按键时重新安排它:
class MyEntry(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.parent = parent
self.after_id = None
...
def onValidate(self, d, i, P, s, S, v, V, W):
if self.after_id:
self.parent.after_cancel(self.after_id)
self.after_id = self.parent.after(1000, self.select_all_text)
return True
请注意,我还在 self.parent
中保存了您作为参数传递给 MyEntry
的根 window,并使用它来调用 after
。
P.S。您实际上并不需要 Entry 的 validatecommand
命令来执行此操作(当然,如果您已经使用了 validatecommand
,则可以)。您可以将函数绑定到每个按键:
class MyEntry(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.parent = parent
self.after_id = None
self.entry = tk.Entry(self)
self.entry.bind('<Key>', self.entry_keypress)
...
def entry_keypress(self, e):
print(self.after_id)
if self.after_id:
self.parent.after_cancel(self.after_id)
self.after_id = self.parent.after(1000, self.select_all_text)