自从tkinter上一次按键以来经过了一段时间后调用函数

时间:2019-03-07 11:20:44

标签: python tkinter keypress tkinter-entry

我在Python的tkinter应用程序中有一个条目。如果用户更改了输入内容,程序将通过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 个答案:

答案 0 :(得分:2)

当您保留对after返回的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

请注意,我还将保存的根窗口作为参数传递给MyEntry中的self.parent,并用它来调用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)