如何在函数后停止 tkinter?
Posted
技术标签:
【中文标题】如何在函数后停止 tkinter?【英文标题】:How do I stop tkinter after function? 【发布时间】:2012-04-04 07:47:50 【问题描述】:我在停止“提要”时遇到问题; cancel 参数似乎对 after 方法没有任何影响。虽然“进纸停止”打印到控制台。
我正在尝试使用一个按钮来启动提要和另一个按钮来停止提要。
from Tkinter import Tk, Button
import random
def goodbye_world():
print "Stopping Feed"
button.configure(text = "Start Feed", command=hello_world)
print_sleep(True)
def hello_world():
print "Starting Feed"
button.configure(text = "Stop Feed", command=goodbye_world)
print_sleep()
def print_sleep(cancel=False):
if cancel==False:
foo = random.randint(4000,7500)
print "Sleeping", foo
root.after(foo,print_sleep)
else:
print "Feed Stopped"
root = Tk()
button = Button(root, text="Start Feed", command=hello_world)
button.pack()
root.mainloop()
随着输出:
Starting Feed
Sleeping 4195
Sleeping 4634
Sleeping 6591
Sleeping 7074
Stopping Feed
Sleeping 4908
Feed Stopped
Sleeping 6892
Sleeping 5605
【问题讨论】:
我不完全确定 tkinter 是如何工作的,但这对我来说看起来很像一个线程问题。如果你取消一个(线程安全的)全局,这能解决问题吗? @mklauber:不,不是线程问题。 Tkinter 是单线程的。 @BryanOakley:谢谢。这就是我发表评论的原因。我不确定,所以我只是想提出这个问题。 【参考方案1】:问题在于,即使您使用True
调用print_sleep
来停止循环,也已经有一个待处理的作业等待触发。按下停止按钮不会触发新作业,但旧作业仍然存在,并且当它调用自身时,它会传入 False 导致循环继续。
您需要取消挂起的作业以使其无法运行。例如:
def cancel():
if self._job is not None:
root.after_cancel(self._job)
self._job = None
def goodbye_world():
print "Stopping Feed"
cancel()
button.configure(text = "Start Feed", command=hello_world)
def hello_world():
print "Starting Feed"
button.configure(text = "Stop Feed", command=goodbye_world)
print_sleep()
def print_sleep():
foo = random.randint(4000,7500)
print "Sleeping", foo
self._job = root.after(foo,print_sleep)
注意:确保在某处初始化self._job
,例如在应用程序对象的构造函数中。
【讨论】:
我需要这样做,但我需要更多细节 - 请您提供一个完整的示例,包括如何“在某处初始化 self._job,例如在您的应用程序对象的构造函数中。”? 如何获取root.after()
的id?致电root.after_cancel()
【参考方案2】:
当您调用root.after(...)
时,它会返回一个标识符。您应该跟踪该标识符(例如,将其存储在实例变量中),然后您可以稍后调用 root.after_cancel(after_id)
来取消它。
【讨论】:
如何获取id?【参考方案3】:这是我的答案,只添加了 3 行代码。答案在于使用.after_cancel(x)
,简单来说就是“停止做'x'工作”。我相信代码的可读性,所以我只对完成这项工作的代码进行了最小的更改。请看一看。谢谢。
from tkinter import Tk, Button
import random
keep_feeding = None
def goodbye_world():
print("Stopping Feed")
button.configure(text="Start Feed", command=hello_world)
print_sleep(True)
def hello_world():
print("Starting Feed")
button.configure(text="Stop Feed", command=goodbye_world)
print_sleep()
def print_sleep(cancel=False):
global keep_feeding
if not cancel:
foo = random.randint(1000, 2500)
print(f"Sleeping foo")
keep_feeding = root.after(foo, print_sleep)
else:
root.after_cancel(keep_feeding)
print("Feed Stopped")
root = Tk()
button = Button(root, text="Start Feed", command=hello_world)
button.pack()
root.mainloop()
【讨论】:
以上是关于如何在函数后停止 tkinter?的主要内容,如果未能解决你的问题,请参考以下文章
单击按钮后如何将输入值(TKinter)传递给其他类中的函数并使用传递的值运行函数[重复]
如何从Tkinter,Python中的Text小部件中移除焦点
tkinter“window.after”循环在夜间 Windows 睡眠/恢复后停止