#python #tkinter #keypress #tkinter-entry
#python #tkinter #нажатие клавиши #tkinter-запись
Вопрос:
У меня есть запись в приложении tkinter на Python. Если пользователь изменяет содержимое записи, программа реагирует с помощью onValidate
функции.
Теперь я хотел бы выделить весь текст в поле ввода, если пользователь некоторое время не нажимал никаких клавиш.
Ниже я попытался select_all_text
после 1000
мс использовать after
функцию, но, похоже, это не сработало.
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 прошло достаточно много времени?
Ответ №1:
Когда вы сохраняете ссылку на идентификатор, который after
возвращается, вы можете отменить его с помощью 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
Обратите внимание, что я также сохранил корневое окно, которое вы передаете в качестве аргумента MyEntry
в self.parent
, и использовал его для вызова after
дальше.
P.S. На самом деле вам не нужна validatecommand
команда Entry для этого (но вы могли бы, если вы уже используете 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)