Tkinter按钮冻结



假设您有这个程序:

import os
from tkinter import *
from time import sleep
def wait():
print('waiting 5 seconds...')
sleep(5)
def close():
root.destroy()

root = Tk()
b = Button(text='click', command=wait)
close = Button(text='close', command=close)
b.pack()
close.pack()
mainloop()

在我点击按钮"之后;点击";,按钮冻结5秒钟,然后恢复正常。我该怎么做才能不冻?(我不想删除按钮动画,我只想让它做按钮动画,然后等待5秒(此外,当我点击";点击";,我无法点击";关闭";。我该如何解决这个问题?

time.sleep((暂停整个应用程序(包括tkinter窗口(,这意味着它将冻结。但是,您可以使用root.after()函数。一个工作示例:

import tkinter
class MyApp:
def __init__(self, parent):
self.root = parent
self.root.geometry("400x400")
self.frame = tkinter.Frame(parent)
self.frame.pack()
self.root.after(3000, self.delayed)
def delayed(self):
print('I was delayed')
if __name__ == "__main__":
root = tkinter.Tk()
app = MyApp(root)
root.mainloop()

使用root.after不会在等待期间冻结您的应用程序。注意:您必须以毫秒为单位指定等待时间(1秒=1000毫秒(

我希望我能帮助你!

由于time.sleep()是一个阻塞函数,因此在函数调用完成之前不会运行任何代码。为了避免这种情况发生,您可以使用threading创建一个等待五秒钟但允许其他代码运行的线程。这被称为多处理,您可以在这里阅读更多关于多处理的信息。

import threading
import time
import tkinter
import os
def wait():
print('waiting 5 seconds...')
threading.Thread(target=time.sleep, args=(5,)).start()
def close():
root.destroy()

root = tkinter.Tk()
b = tkinter.Button(text='click', command=wait)
close = tkinter.Button(text='close', command=close)
b.pack()
close.pack()
root.mainloop()

Tkinter一开始可能有点令人困惑。大多数人认为Tkinter是在与代码分离的线程上运行的,但事实并非如此。这意味着当你使用time.sleep时,你的程序会冻结该时间,其中包括Tkinter。如果你想要达到的目标是等待5秒((;DoSomething((;我建议您执行以下操作:

import time
def wait():
print('waiting 5 seconds...')
stop = time.time() + 5
while time.time() <= stop:
time.sleep(.001)
DoSomething()

这也不是完美的解决方案,因为它仍然需要睡眠,但更好。你可以用pass代替它,但我倾向于把time.sleep放在专门为等待而设计的while循环中的原因是,如果你只有while x: pass,它会提升你的CPU核心,这可能会在低核心数量的计算机中造成显著的滞后。这里的想法只是放一些需要一些时间的东西,这样你的CPU就不会疯掉。一个可能的替代方案是print('r'),我还没有测试过自己,但可以工作,不会造成Tkinter延迟,它只是将光标设置回行的开头。如果你还没有转到新的行,这将覆盖那里的内容,所以要注意。但这可能会更好,因为就处理能力而言,输出到屏幕实际上需要相当长的时间,但不会阻止Tkinter。若要对此进行测试(假设您在Windows上(,可以按LCtrl+LShift+Esc打开"任务管理器",按更多详细信息(如有必要(,然后转到"性能"选项卡。确保已选择CPU,然后右键单击图形并选择"将图更改为">逻辑处理器,这将分别向您显示每个核心的利用率。默认情况下,python只在一个内核中运行,尽管它可以随意切换使用的内核。

最新更新