使用Tkinter进行线程处理(有或没有队列)

时间:2014-03-13 14:59:42

标签: python multithreading callback tkinter queue

我有一个更高级的代码,但这一切都来自这个简单的例子:

from Tkinter import *
import time

def destroyPrint():
    global printOut
    try:
        printOut.destroy()
    except:
        pass


def sendData():
    global new
    global printOut
    for i in range(6):
        destroyPrint()
        time.sleep(1)
        printOut=Label(new,text=i,font=('arial',15,'bold'))
        printOut.place(x=300,y=500)


def newWindow():
    global new
    print("ok")
    new=Toplevel()
    new.minsize(800,600)
    functionButton=Button(new,text="Send me",width=20,height=20, command=sendData)
    functionButton.place(x=300,y=150)


main = Tk()
main.minsize(800, 600)
menu=Button(main,text="Send data",width=20,height=20, command=newWindow)
menu.place(x=300,y=150)
mainloop()

在这个简单的例子中,我想启动sendData函数,它将在每次循环迭代时相应地更新printOut Label。我们都知道它没有,它会挂起,直到功能完成,并打印最后一个数字(5)。

我尝试了无数的线程和排队示例,而且我的失败很严重。 请简单澄清这个例子,当你需要在另一个线程中执行Tkinter元素时,如何正确地进行线程化。

我真的很沮丧,我在这一步花了最后两天......

1 个答案:

答案 0 :(得分:2)

您必须添加update_idletasks()才能更新标签。而不是销毁和创建,只需更新文本,并在Tkinter中使用after()而不是sleep,因为它会生成一个新进程,而time.sleep()会在睡眠时挂起程序。

from Tkinter import *
import time

def sendData():
    global new
    ##global printOut
    printOut=Label(new,text="0",font=('arial',15,'bold'))
    printOut.place(x=300,y=500)
    for x in range(6):
        ##destroyPrint()
        printOut.config(text=str(x))
        new.update_idletasks()
        time.sleep(1)

def newWindow():
    global new
    print("ok")
    new=Toplevel()
    new.minsize(800,600)
    functionButton=Button(new,text="Send me",width=20,
                  height=20, command=sendData)
    functionButton.place(x=300,y=150)


main = Tk()
main.minsize(800, 600)
menu=Button(main,text="Send data",width=20,height=20, command=newWindow)
menu.place(x=300,y=150)
main.mainloop()