问题描述
使用 tkinter,如何使用 after
方法使函数定期运行?
With tkinter, how can I use the after
method to make a function run periodically?
例如,我有一个 speak
函数,它只在控制台中打印一些内容:
For instance, I have a speak
function that only prints something in the console:
def speak():
print("Hello, world!")
如何使用after
方法每秒调用speak
函数?
How can I use the after
method to call the speak
function every second?
推荐答案
注意:以下代码是在 Python 3.5 中编写和测试的.例如,在调用 super
时可能需要进行一些细微的更改.
Note: the following code is written and tested in Python 3.5. Minor changes might be needed, for instance, when calling super
.
文档 描述了 Widget.after
方法如下:
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.
安排函数
after
方法主要用于在给定的延迟之后安排函数调用.例如,下面的代码安排一秒后对函数的调用:
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!
使函数定期运行
为了让一个函数周期性地运行,可以让它在自己的函数体的末尾调用自己.但是,after
是来自 Widget
类的方法,因此需要一个小部件.因此,最好的选择通常是将调度函数放在扩展 Widget
的类中.
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
.
以下代码每隔一秒在控制台打印一次"Hello world!"
.
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()
使用参数
人们可能希望将参数传递给定期运行的方法.为此,after
方法将回调之后的每个参数解包为要传递给回调的参数.例如,root.after(1000, foo, a, b, c)
将调度对 foo(a, b, c)
的调用.以下示例展示了如何使用此功能来确定函数的行为.
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!")
取消通话
after
方法返回一个字符串,对应于调用的 id.它可以传递给 after_cancel
方法,以取消预定的调用.
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.
以下示例将开始每秒打印 "Hello world!"
,但在按下按钮时停止打印.
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()
附注
应牢记以下几点.
after
方法并不能保证在给定的延迟之后*精确* 调用回调,但*至少*在它之后调用.因此,after
不应用于需要精度的地方.- 使用
time.sleep
来安排或定期运行函数可能很诱人.在 GUI 上工作时必须避免这种情况,因为 `sleep` 将暂停当前线程,该线程大部分时间是主线程.例如,这可能会停止小部件的刷新,程序将停止响应.
- 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.
这篇关于如何使用 after 方法使回调定期运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!