Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
549 views
in Technique[技术] by (71.8m points)

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

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 something in the console:

def speak():
    print("Hello, world!")

How can I use the after method to call the speak function every second?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...