Python - 循环锁应用程序

时间:2015-02-20 22:19:37

标签: python tkinter

我正在为我正在处理的应用程序敲打一段时间。经过几个小时试图调试接口锁定的问题,没有其他任何事情可以发生,我发现它是可怕的While循环。请参阅下面的示例并运行它。当您通过单击按钮启动while循环时,您无法在屏幕上执行任何其他操作。在这种情况下,它只是一个需要按下的简单警报按钮。

from Tkinter import *
import tkMessageBox

root = Tk()
root.geometry("450x250+300+300")
root.title("Raspberry PI Test")

def myloop():
    count = 0
    while (count < 500):
       print 'The count is:', count
       count = count + 1

    print "Good bye!"

def mymessage():
    tkMessageBox.showinfo(title="Alert", message="Hello World!")

buttonLoop = Button(root, text="Start Loop", command=myloop)
buttonLoop.place(x=5, y=15)

buttonMessage = Button(root, text="Start Loop", command=mymessage)
buttonMessage.place(x=85, y=15)


root.mainloop()

如何在计数完成之前有一个需要运行的循环,并且仍能在我的应用程序中执行其他任务?我还应该注意到,我使用Thread尝试过同样的事情并不重要。在您可以执行任何操作之前,UI仍在等待While循环结束。

3 个答案:

答案 0 :(得分:2)

现在我明白你想要什么(秒表)我会推荐root.after命令

from Tkinter import *
import tkMessageBox
import threading
import time
root = Tk()
root.geometry("450x250+300+300")
root.title("Raspberry PI Test")
print dir(root)
count = 0
def start_counter():
    global count
    count = 500
    root.after(1,update_counter)
def update_counter():
    global count
    count -= 1
    if count < 0:
        count_complete()
    else:
        root.after(1,update_counter)

def count_complete():
    print "DONE COUNTING!! ... I am now back in the main thread"
def mymessage():
    tkMessageBox.showinfo(title="Alert", message="Hello World!")

buttonLoop = Button(root, text="Start Loop", command=myloop)
buttonLoop.place(x=5, y=15)

buttonMessage = Button(root, text="Start Loop", command=mymessage)
buttonMessage.place(x=85, y=15)


root.mainloop()

(原始答案如下)

使用线程

from Tkinter import *
import tkMessageBox
import threading
import time
root = Tk()
root.geometry("450x250+300+300")
root.title("Raspberry PI Test")
print dir(root)
def myloop():
    def run():
        count = 0
        while (count < 500) and root.wm_state():
           print 'The count is:', count
           count = count + 1
           time.sleep(1)

        root.after(1,count_complete)
    thread = threading.Thread(target=run)
    thread.start()
def count_complete():
    print "DONE COUNTING!! ... I am now back in the main thread"
def mymessage():
    tkMessageBox.showinfo(title="Alert", message="Hello World!")

buttonLoop = Button(root, text="Start Loop", command=myloop)
buttonLoop.place(x=5, y=15)

buttonMessage = Button(root, text="Start Loop", command=mymessage)
buttonMessage.place(x=85, y=15)


root.mainloop()

请注意,当您显示将在Windows api级别阻止的信息框时,线程计数将等到关闭...为了解决这个问题,您可以用多处理替换线程我认为

答案 1 :(得分:0)

我对TKinter并不是很了解,但从我的阅读中可以清楚地看到,你需要在while循环中使用一些TKinter方法来更新你的文本框。 TKinter在事件循环上运行,因此您必须从代码发送信号以重新输入TKinter的执行。

您发现自己的while循环阻止执行了您的用户界面更新,您做得非常出色。因此,您需要暂停执行counting's并让TKinter更新用户界面,而不是线程化。

这个tutorial提供了一个很好的例子。关键是在第24行,他打电话给root.update,我认为这违反了你的程序让TKinter做了它。

答案 2 :(得分:0)

这是最终的代码,只是为了证明该线程有效。计数在屏幕上同时显示。再次感谢Joran!

from Tkinter import *
import tkMessageBox
import threading
import time
root = Tk()
root.geometry("450x250+300+300")
root.title("Raspberry PI Test")
showResults = StringVar()
showResults.set('0')
print dir(root)
def myloop():
    def run():
        count = 0
        while (count < 1000) and root.wm_state():
           print 'The count is:', count
           showResults.set(count)
           count = count + 1
           #time.sleep(1)

        root.after(1,count_complete)
    thread = threading.Thread(target=run)
    thread.start()
def count_complete():
    print "DONE COUNTING!! ... I am now back in the main thread"
def mymessage():
    tkMessageBox.showinfo(title="Alert", message="Hello World!")

buttonLoop = Button(root, text="Start Loop", command=myloop)
buttonLoop.place(x=5, y=15)

buttonMessage = Button(root, text="Message", command=mymessage)
buttonMessage.place(x=85, y=15)

l2 = Label(root, width=15, height=4, font=("Helvetica", 16), textvariable=showResults, background="black", fg="green")
l2.place(x=15, y=65)

root.mainloop()