【发布时间】:2017-02-10 20:38:30
【问题描述】:
我有一个循环旋转轮 gif 以显示正在运行的进程的函数。当进程完成时,该函数会再次以不同的值(开/关)调用,Label 更改为 ✓。如果我只有来自threadspawner() 的几个线程启动,那么它们就可以很好地完成并将label 更改为✓。如果我同时启动很多线程(比如 12 个),那么线程完成得很好,但是一个或两个标签的纺车有时不会变成 ✓。
请注意,在下面的示例中,我无法让加载程序停止并更改为 ✓。也许这是我搞砸的一部分,但在我的代码中它切换得很好。
我应该以不同的方式表示负载轮还是以不同的方式调用 loader('off')?
我尝试为每个线程使用一个全局变量,并在线程启动时将其设置为 True,然后在线程结束时将其设置为关闭。这仅在我更新加载器循环中的变量以获取新值时才有效,这意味着我必须为每个线程创建一个不同的加载器函数,这是很多额外的代码。我尝试使用while 循环而不是if,但它没有任何改变。
我想为每个线程运行的纺车使用相同的加载器函数。如果这不是最好的方法,请指出正确的方向。
from tkinter import *
import time
import threading
main = Tk()
def threadspawner():
global var1
global var2
print(var1)
if var1.get() == 2:
thread1 = threading.Thread(target=lambda: loader(lbl1, 'on')) #<-- starts the spinning wheel to show that something is happening
thread1.start()
time.sleep(1) #start doing stuff here
loader(lbl1, 'off') #<-- Turns off the spinning wheel
thread1.join()
if var2.get() == 2:
thread2 = threading.Thread(target=lambda: loader(lbl1, 'on')) #<-- starts the spinning wheel to show that something is happening
thread2.start()
time.sleep(2)
loader(lbl2, 'off')#<-- Turns off the spinning wheel
thread2.join()
var1 = IntVar()
chk1 = Checkbutton(main, text='process1', onvalue=2, offvalue=0, variable=var1)
chk1.grid(row=1)
lbl1 = Label(main, text='')
lbl1.grid(row=1, column=1)
var2 = IntVar()
chk2 = Checkbutton(main, text='process2', variable=var2)
chk2.grid(row=2)
lbl2 = Label(main, text='')
lbl2.grid(row=2, column=1)
strt = Button(main, text='Start', command=lambda: threading.Thread(target=lambda: threadspawner()).start())
strt.grid(columnspan=2)
def loader(label, switch):
global lbl1
global lbl2
#im using images for my program but you do not have them so I use keyboard entries below to represent
#img = PhotoImage(file='icons\\wheel.gif', format="gif -index 0")
#img1 = PhotoImage(file='icons\\wheel.gif', format="gif -index 1")
#img2 = PhotoImage(file='icons\\wheel.gif', format="gif -index 2")
if switch == 'off':
label['text'] = '✓'
return
if switch == 'on':
print('starting loop')
if switch == 'on':
label['text'] = '/'
time.sleep(.1)
if switch == 'on':
label['text'] = '-'
time.sleep(.1)
if switch == 'on':
label['text'] = '\\'
time.sleep(.1)
if switch == 'on':
loader(label, 'on')
main.mainloop()
【问题讨论】:
-
这里似乎没有任何东西可以保证您在打开微调器之后关闭它。
-
在线程启动时使用变量“on”,最后使用变量“off”,然后在加载程序循环中更新变量,这是唯一可靠的方法吗?
-
你为什么要从不同的线程关闭和打开它?为什么要在等待其他线程完成之前关闭微调器?
-
您不能从多个线程安全地访问 Tkinter 函数。使用线程处理冗长的任务是一个合理的解决方案,但是您必须以某种方式安排代表它们的任何 GUI 更新被传递到主线程(也许通过队列),并在那里执行。
-
@user2357112 我想在用于启动该线程的 Checkbutton 旁边表示正在运行的线程。有一个纺车是我找到的最好的方式。为简单起见,我尝试使用加载器功能控制每个线程的纺车。您如何建议我在 GUI 中向用户显示线程正在运行/已完成?
标签: python python-3.x text tkinter