2013-04-04 67 views
1

我有以下代码的部分的问题:延迟方法执行命令

my_var = tk.StringVar(value="start") 
my_label = tk.Label(self.root, textvariable=my_var) 
def my_method(input): 
    my_var.set("working") 
    #make a method call to an external Python API; can take a few mins to finish 
    my_var.set("complete") 

tk.Button(self.root, text="GO!", command=lambda: my_method(input)) 

我有一个按钮,单击时,应该执行my_method应该最初改变my_label文本working,在外部API中处理一些操作,然后将标签更新为complete。实际发生的是my_method被调用,标签的文本不会改变,API调用需要几分钟,然后我的标签更新为complete。我假设它可以快速处理两个设置命令,但我只能看到最终的设置值。

是否有这样的事情发生的原因(我做错了什么),并有解决方案吗?如果这是预期的行为,有人可以解释为什么是这样吗?

虽然写这个,我想也许启动一个线程来执行初始设置调用,看看是否会工作。我宁愿更简单的解决方案。

回答

3

Tkinter需要您立即从回调中返回,以便它可以回到Tk.mainloop中需要执行的处理。如果无法执行此处理,它将无法更新您的标签文本。 (它也不能处理正常的处理事件,如拖动窗口等)

回调不应该长时间挂在主线程上,因此。如果为他们做了一些耗时的处理,它应该在一个单独的线程中完成。

+0

如果我创建了一个新线程来进行进程调用,那么如何防止用户在完成之前能够与Tk进行交互?是否可以冻结主循环直到线程结束?实质上,我需要阻止进一步的用户与GUI的交互,直到API调用完成。 – 2013-04-04 10:55:59

+2

不要冻结主循环;相反,您可以将按钮状态设置为“DISABLED”,直到过程完成。对于按钮'b',设置'b.config(state = DISABLED)'。然后当你完成后,将其设置回:'b.config(state = NORMAL)' – twasbrillig 2013-04-04 10:59:47

+0

谢谢,这当然是一个更好的方法。 – 2013-04-04 11:04:28