为什么进度条只能使用“打印”命令,而不能使用tkinter?

时间:2019-12-26 16:47:54

标签: python tkinter printing progress-bar progress

我想了解为什么这段代码:

import time

for i in range(1,11):
    print(i)
    time.sleep(1)

(按应有的方式)每1秒显示1到10之间的数字,而该代码为:

from tkinter import *
import time

root = Tk()

for i in range(1,11):
    Label(root, text = i).grid(row=0, column=i-1, padx=5, pady =5)
    time.sleep(1)

root.mainloop()

等待10秒钟,然后显示带有10个数字的窗口(而不是一个一个地添加)。 我知道这是一个愚蠢的问题,但我真的听不懂!非常感谢!亚历山德罗

2 个答案:

答案 0 :(得分:3)

大多数GUI的工作方式与您期望的不同。

它们以异步方式工作,这意味着您可以设置窗口并启动事件循环。 此事件循环将显示您在调用事件循环之前设置的所有小部件,标签等,并等待任何事件(GUI事件,例如鼠标或键盘事件,计时器事件,甚至是网络事件)。

遇到任何事件时,将调用与该事件相关的代码,并且该代码可以请求更改GUI(显示或隐藏元素,更改图形小部件的标签或属性)但是只有当您将控制权交还给事件循环时(处理事件的代码完成时),才会执行GUI。

在给定的代码中,您可以使用睡眠语句在for循环中更改标签,但是只有在for循环完成后,才可以调用主循环,并且此时此刻将显示GUI的最终状态。

因此,您遇到的几乎是所有GUI /异步应用程序的已知问题。

您必须重写代码,以启动一个计时器事件,并在计时器事件触发时,一个函数将设置标签并将计数器增加1。如果计数器不是11,它将重新启动另一个计时器< / p>

答案 1 :(得分:3)

这是因为time.sleep函数位于root.mainloop函数之前。

root.mainloop是导致窗口显示在屏幕上并开始运行的原因。相反,我建议使用window.after,因为它告诉窗口在屏幕上显示一段时间后再运行一个函数。

这是您可以进行修改的一个示例(虽然不是很好,但是可以工作):

from tkinter import *
import time

root = Tk()
progress = 0
end = 10

def update_progress():
    global progress
    progress += 1
    Label(root, text = progress).grid(row=0, column=progress-1, padx=5, pady =5)
    if progress < end: root.after(1000,update_progress)  # Tell the window to call this function in 1000ms (1 second)

root.after(0,update_progress)  # Tell the window to run the update_progress function 0ms after now.
root.mainloop()

我建议您查看gelonida的答案,以解释您的原始代码为何不起作用以及以后使用GUI编程时需要记住的事情。