How to use the after method to make a callback run periodically?

后端 未结 1 1860
生来不讨喜
生来不讨喜 2020-12-03 20:47

With tkinter, how can I use the after method to make a function run periodically?

For instance, I have a speak function that only prints so

相关标签:
1条回答
  • Note: the following code is written and tested in Python 3.5. Minor changes might be needed, for instance, when calling super.

    The documentation describes the Widget.after method as follows:

    after(delay_ms, callback=None, *args)

    Registers an alarm callback that is called after a given time.


    Scheduling a function

    The after method is primarily used to schedule a function call after a given delay. For instance, the following code schedules a call to a function after one second:

    import tkinter as tk
    
    def speak():
        print("Hello world!")
    
    root = tk.Tk()
    root.after(1000, speak)
    
    # Output
    Hello world!
    

    Making a function run periodically

    In order to make a function run periodically, one can make it call itself at the end of its own body. However, after is a method from the Widget class, so a widget is needed. Therefore, the best choice is generally to put the scheduled function inside of a class extending Widget.

    The following code prints "Hello world!" every other second in the console.

    import tkinter as tk
    
    class Foo(tk.Tk):
        def periodically_speak(self):
            print("Hello world!")
            self.after(2000, self.periodically_speak)
    
    foo = Foo()
    foo.periodically_speak()
    

    Using parameters

    One might want to pass parameters to a method that runs periodically. For this purpose, the after method unpacks every parameter after the callback as the parameters to pass to the callback. For instance, root.after(1000, foo, a, b, c) will schedule a call to foo(a, b, c). The following example shows a use of this feature to determine the behaviour of the function.

    import tkinter as tk
    
    class Foo(tk.Tk):
        def periodically_speak(self, text):
            print(text)
            self.after(2000, self.periodically_speak, text)
    
    foo = Foo()
    foo.periodically_speak("Good night world!")
    

    Canceling a call

    The after methods returns a string, that corresponds to the call's id. It can be passed to the after_cancel method, in order to cancel a call that was scheduled.

    The following example will start printing "Hello world!" every second, but will stop when pressing the button.

    import tkinter as tk
    
    class Foo(tk.Tk):
        def __init__(self):
            super().__init__()
            self.callId = None
            self.button = tk.Button(self, text="Stop", command=self.stop)
            self.button.pack()
    
        def periodically_speak(self):
            print("Hello world!")
            self.callId = self.after(2000, self.periodically_speak)
    
        def stop(self):
            if self.callId is not None:
                self.after_cancel(self.callId)
    
    foo = Foo()
    foo.periodically_speak()
    

    Side notes

    The following points should be kept in mind.

    • The after method does not guarantee that the callback will be called *exactly* after the given delay, but *at least* after it. As a consequence, after should not be used where precision is required.
    • It might be tempting to use time.sleep in order to schedule or periodically run a function. This must be avoided when working on a GUI, because `sleep` will pause the current thread, which most of the time is the main thread. For example, this could halt the refresh of the widgets, the program would stop responding.
    0 讨论(0)
提交回复
热议问题