我一直在尝试在Python tkinter GUI中设置一个进度条,以显示进程正在运行。该过程较长,我没有真正的方法来衡量进度,因此需要使用不确定的进度条。然而,我真的不喜欢ttk不确定进度条反弹来回的样式。我希望有一个可以在进度条上来回滚动的进度条,就像这张图片所示。 这在tkinter中可能吗?
#!/usr/bin/env python3
import tkinter
import tkinter.ttk as ttk
root = tkinter.Tk()
frame = ttk.Frame()
pb = ttk.Progressbar(frame, length=300, mode='determinate')
frame.pack()
pb.pack()
pb.start(25)
root.mainloop()
我知道这是一个旧问题,但我已经找到了一个方法来解决这个问题,适用于任何正在编写tkinter的人。
我一直在开发一个tkinter应用程序,并确定处理tkinter对象时,绝对需要一个单独的线程。尽管通过与mainloop()
方法以外的方式处理tkinter对象显然是不受欢迎的,但对我而言效果很好。我从未遇到过主线程不在主循环中
的错误,并且从未遇到过没有正确更新的对象。
我稍微修改了Corey Goldberg的代码并使其工作。这就是我的成果(其中一些解释在注释中)。
import tkinter
import tkinter.ttk as ttk
import threading
def mainProgram(): # secure the main program initialization in its own def
root = tkinter.Tk()
frame = ttk.Frame()
# You need to use indeterminate mode to achieve this
pb = ttk.Progressbar(frame, length=300, mode='indeterminate')
frame.pack()
pb.pack()
# Create a thread for monitoring loading bar
# Note the passing of the loading bar as an argument
barThread = threading.Thread(target=keepLooping, args=(pb,))
# set thread as daemon (thread will die if parent is killed)
barThread.daemon=True
# Start thread, could also use root.after(50, barThread.start()) if desired
barThread.start()
pb.start(25)
root.mainloop()
def keepLooping(bar):
# Runs thread continuously (till parent dies due to daemon or is killed manually)
while 1:
"""
Here's the tricky part.
The loading bar's position (for any length) is between 0 and 100.
Its position is calculated as position = value % 100.
Resetting bar['value'] to 0 causes it to return to position 0,
but naturally the bar would keep incrementing forever till it dies.
It works, but is a bit unnatural.
"""
if bar['value']==100:
bar.config(value=0) # could also set it as bar['value']=0
if __name__=='__main__':
mainProgram()
我添加了if __name__=='__main__':
,因为我觉得它更好地定义了作用域。
顺便说一下,我发现使用while 1:
运行线程会使特定线程的CPU占用率达到20-30%。通过导入time
并在之后使用time.sleep(0.05)
可以轻松解决此问题,从而显着降低CPU使用率。
在Win8.1,Python 3.5.0上进行了测试。